Find out what input delay is, and learn techniques to reduce it for faster interactivity.
Interactions on the web are complicated things, with all sorts of activity occurring in the browser to drive them. What they all have in common, though, is that they incur some input delay before their event callbacks begin to run. In this guide, you'll learn what input delay is, and what you can do to minimize it so your website's interactions run faster.
What is input delay?
Input delay is the period of time beginning from when the user first interacts with a page—such as tapping on a screen, clicking with a mouse, or pressing a key—up to when the event callbacks for the interaction begin to run. Every interaction begins with some amount of input delay.
Some portion of the input delay is unavoidable: it always takes some amount of time for the operating system to recognize an input event and pass it to the browser. However, that portion of the input delay is often not even noticeable, and there are other things that happen on the page itself that can make input delays long enough to cause problems.
How to think about input delay
Generally speaking, you want to keep every part of an interaction as short as possible so that your website has the best chance of meeting the Interaction to Next Paint (INP) metric's "good" threshold, regardless of the user's device. Keeping input delay in check is just one part of meeting that threshold.
Consequently, you'll want to aim for the shortest input delay possible to meet INP's "good" threshold. You should be aware, though, you can't expect to eliminate input delays entirely. As long as you're avoiding excessive main thread work while users are attempting to interact with your page, your input delay should be low enough to avoid problems.
How to minimize input delay
As said previously, some input delay is unavoidable, but on the other hand, some input delay is avoidable. Here are some things to consider if you're struggling with long input delays.
Avoid recurring timers that kick off excessive main thread work
There are two commonly used timer functions in JavaScript that can contribute to input delay: setTimeout
and setInterval
. The difference between the two is that setTimeout
schedules a callback to run after a specified time. setInterval
, on the other hand, schedules a callback to run every n milliseconds in perpetuity, or until the timer is stopped with clearInterval
.
setTimeout
is not problematic in itself—in fact, it can be helpful in avoiding long tasks. However, it depends on when the timeout occurs, and whether the user attempts to interact with the page when the timeout callback runs.
Additionally, setTimeout
can be run in a loop or recursively, where it acts more like setInterval
, though preferably not scheduling the next iteration until the previous one is completed. While this means the loop will yield to the main thread every time setTimeout
is called, you should take care to ensure its callback doesn't end up doing excessive work.
setInterval
runs a callback on an interval, and is therefore much more likely to get in the way of interactions. This is because—unlike a single instance of a setTimeout
call, which is a one-off callback that may get in the way of a user interaction—setInterval
's recurring nature makes it much more likely that it will get in the way of an interaction, thus increasing the interaction's input delay.
If timers are occurring in first-party code, then you have control over them. Evaluate whether you need them, or do your best to reduce the work in them as much as possible. However, timers in third-party scripts are a different story. You often don't have control over what a third-party script does, and fixing performance issues in third-party code often involves working with stakeholders to determine whether a given third-party script is necessary, and if so, establish contact with a third-party script vendor to determine what can done to fix performance issues they may cause on your website.
Avoid long tasks
One way to mitigate long input delays is to avoid long tasks. When you have excessive main thread work that blocks the main thread during interactions, that will add to the input delay for them before the long tasks have had a chance to finish.
Besides minimizing the amount of work you do in a task—and you should always strive to do as little work as possible on the main thread—you can improve responsiveness to user input by breaking up long tasks.
Be mindful of interaction overlap
A particularly challenging part of optimizing INP can be if you have interactions that overlap. Interaction overlap means that after you've interacted with one element, you make another interaction with the page before the initial interaction has had a chance to render the next frame.
Sources of interaction overlap may be as simple as users making many interactions in a short period of time. This can occur when users type in form fields, where many keyboard interactions can occur in a very short period of time. If the work on a key event is especially expensive—such as in the common case of autocomplete fields where network requests are made to a back end—you have a couple of options:
- Consider debouncing inputs to limit the amount of times an event callback executes in a given period of time.
- Use
AbortController
to cancel outgoingfetch
requests so the main thread doesn't become congested handlingfetch
callbacks. Note: anAbortController
instance'ssignal
property can also be used to abort events.
Another source of increased input delay due to overlapping interactions can be expensive animations. In particular, animations in JavaScript may fire many requestAnimationFrame
calls, which may get in the way of user interactions. To get around this, use CSS animations whenever possible to avoid queueing potentially expensive animation frames—but if you do this, make sure you avoid non-composited animations so that animations run mainly on the GPU and compositor threads, and not on the main thread.
Conclusion
While input delays may not represent the majority of the time your interactions take to run, it's important to understand that every part of an interaction takes up an amount of time that you can reduce. If you're observing long input delay, then you have opportunities to reduce it. Avoiding recurring timer callbacks, breaking up long tasks, and being aware of potential interaction overlap can all help you to reduce input delay, leading to faster interactivity for your website's users.
Hero image from Unsplash, by Erik Mclean.