Självhosta Google Fonts för bättre Core Web Vitals
Lär dig hur du självhostar Google Fonts och optimerar dessa typsnitt för bättre Core Web Vitals

Interaction to Next Paint (INP) issues caused by input delay
This page is part of our Interaction to Next Paint (INP) series. INP measures the total time from a user interaction to the next visual update. Input delay is the first of three phases that make up the INP, followed by processing time and presentation delay. If you are new to INP, read our guide on how to identify and fix INP issues first.
In this article we focus on input delay: what causes it, how it affects the Interaction to Next Paint, and how to minimize input delays to improve your INP scores.
INP TIP: most of the time
input delay will occur during the early loading stages of the webpage. This is when the browser is busiest parsing and executing scripts.
Table of Contents!
- Interaction to Next Paint (INP) issues caused by input delay
- What is input delay?
- Input delay and the INP
- The importance of input delay
- Input delay causes
- Minimize input delay
- Breaking up tasks with scheduler.yield()
- Prioritizing tasks with scheduler.postTask()
- Practical implications
- Explore the other INP phases
What is input delay?

Input delay refers to the time it takes for the browser to begin processing an event callback after a user interacts with a web page (for example, clicking a button or pressing a key). While there is always some input delay (even browsers need time to schedule the callbacks), excessive input delay occurs when the browser is busy performing other scheduled tasks and cannot immediately schedule the callbacks requested by the interaction.
During input delay, the user has already performed their action (click, tap, or keypress) but the browser has not yet started running the associated event handler. The user sees no response whatsoever. This is different from processing time, where the event handler is actively running, and from presentation delay, where the browser is rendering the visual update. Input delay is pure waiting time caused by a congested main thread.
Input delay and the INP
The Interaction to Next Paint (INP) can be broken down into 3 sub-parts: "Input Delay", "Processing Time", and "Presentation Delay".

You might notice that there are naming similarities between the Input Delay and the older Core Web Vital "First Input Delay" (FID). The Interaction to Next Paint replaced FID as a Core Web Vital in March 2024. The First Input Delay measured only the time between the first interaction and the event callback. Even though FID has been retired, input delay still plays an important role in improving web responsiveness because input delay is at the basis of every Interaction to Next Paint measurement.
The importance of input delay
Since many developers think about improving the INP in terms of optimizing callback functions (optimizing the processing time), input delay is often overlooked. Granted, input delay is not usually the biggest part of the INP, but if we optimize the input delay we will often optimize all INP interactions at once. Reducing input delay lifts every interaction on the page, not just the worst one.

At CoreDash we collect millions of Core Web Vitals data points each hour. Based on that data, input delay accounts for approximately 18% of the Interaction to Next Paint. While that is not nearly as much as presentation delay or processing time, it is still a significant portion. More importantly, input delay is often the easiest phase to reduce because the root cause is almost always "too much JavaScript running at the wrong time."
Input delay causes
Input delay occurs when the main thread is busy executing other tasks. These tasks can originate from:

- Early tasks. Normal, deferred, and async scripts that are enqueued early on will create early tasks. These are the most common source of input delay because they execute during the critical startup window when users are most likely to interact with the page.
- Scheduled tasks. Some tasks
do not run at the start of the page load but might be scheduled for after the page has been
loaded. These tasks can also interfere with the INP and cause an input delay. For example,
scripts that run after the
window.onloadevent or scripts that get delayed by so-called optimization plugins. Learn more about when to use async vs defer for JavaScript. - Repeat tasks. Recurring tasks via
setInterval()that take a relatively long time to execute and co-occur with the INP. - Overlapping callbacks. Overlapping callbacks are a common cause of input delay. Multiple
callbacks scheduled close together can create a queue, delaying the processing of the next
interaction. For example, a
mouseoverhandler that fires just before aclickhandler can push the click's processing back by the duration of the mouseover task.
Minimize input delay
- Break up long early tasks into multiple smaller tasks. During long tasks the browser
cannot respond to user input, while after each short task the browser can respond to user input.
Break up long tasks with
scheduler.yield()or by wrapping each function in a timeout of 0 withsetTimeout(callback, 0). - Manage interactive elements. Consider not presenting interactive elements (like a search bar) before the JavaScript code that controls them is fully loaded. This will prevent early clicks for elements that are not ready to receive clicks. To optimize the UX for this pattern you could either prioritize loading the necessary JavaScript or temporarily hide/disable the element until it is functional.
- Idle time script execution. Schedule non-critical scripts to run during browser idle
periods with
requestIdleCallback(). This function runs when the browser is idle and does not need to process user input. - Use web workers to run JavaScript off the browser's main thread. Web workers allow scripts to run off the main thread. This will prevent the main thread from blocking and causing INP input delay issues.
- Check for input pending during repeat tasks. Before executing a set of scheduled tasks, check for pending input before starting the tasks. If there is any input pending, yield to the main thread first.
- Remove unneeded code. Regularly audit your scripts and remove any unnecessary code or even entire scripts, because each line of code can potentially cause an input delay that affects the Interaction to Next Paint. See our guide on 14 methods to defer JavaScript for practical techniques.
Breaking up tasks with scheduler.yield()
The scheduler.yield() API is the recommended way to break up long tasks. Unlike setTimeout(callback, 0), which places the continuation at the back of the task queue, scheduler.yield() preserves the task's priority. This means the browser will resume your code as soon as possible after handling any pending user input. Here is a reusable helper function:
async function yieldToMain() {
if ('scheduler' in window && 'yield' in window.scheduler) {
return await window.scheduler.yield();
}
// Fallback for browsers without scheduler.yield()
return new Promise((resolve) => {
setTimeout(resolve, 0);
});
}
// Example: break up a long initialization sequence
async function initializeApp() {
loadCriticalFeatures();
await yieldToMain(); // Let the browser handle any pending input
loadSecondaryFeatures();
await yieldToMain();
loadAnalytics();
await yieldToMain();
loadNonEssentialWidgets();
}
Prioritizing tasks with scheduler.postTask()
While scheduler.yield() breaks up tasks, scheduler.postTask() gives you fine-grained control over task priority. The API accepts three priority levels: "user-blocking" for critical tasks requiring the highest priority, "user-visible" for medium priority tasks, and "background" for the lowest priority tasks that should run during idle time.
Using postTask() you can ensure that non-essential work does not block user interactions. Here is a practical example that schedules analytics work at background priority while keeping UI updates at the highest priority:
// High priority: UI feedback runs first
scheduler.postTask(() => {
showLoadingSpinner();
}, { priority: 'user-blocking' });
// Medium priority: fetch data
scheduler.postTask(async () => {
const data = await fetchSearchResults(query);
renderResults(data);
}, { priority: 'user-visible' });
// Low priority: analytics can wait
scheduler.postTask(() => {
trackSearchEvent(query);
sendToAnalytics('search', { query });
}, { priority: 'background' });
Check the browser support table for scheduler.postTask() before using it in production. For browsers that do not support the API, fall back to requestIdleCallback() for background tasks and queueMicrotask() for high-priority tasks.
Practical implications
Let's address the most important question: "What does this all mean for my site?" Below are specific recommendations for WordPress and React/Next.js sites.
WordPress
WordPress, due to its plugin-driven architecture, often comes with a theme and a large number of plugins. Both the plugins and the themes often rely on JavaScript for functionality. Since these plugins and themes are maintained by third-party developers, you have no control over the contents. This means that you cannot change the files and optimize "bad code." Even if the scripts behave nicely today, there is no guarantee that they will do so after the next update.
To minimize input delay and optimize the Interaction to Next Paint (INP) on WordPress, take the following steps:
- Avoid using plugins whenever possible. While plugins are an easy way to add functionality, they often add scripts to the page. Those scripts will cause an input delay that impacts the INP. For each plugin, ask yourself: can I achieve the same functionality with custom code or a server-side solution?
- Choose lightweight themes. Many WordPress themes "offer everything." While that seems like a great idea, it means they are likely filled with functionality that is not used but does take up valuable CPU time.
- Avoid page builders. Page builders like Elementor or WPBakery give you a user-friendly, visual interface for building layouts. Unfortunately, they often rely on heavy scripts for presenting that layout to visitors.
- Only load scripts when they are needed. WordPress has a tendency to load all scripts on all pages. To fix this, create a child theme and unregister unneeded scripts per page type:
function my_deregister_scripts() {
if ( ! is_page( 'contact' ) ) {
// Deregister contact form script on non-contact pages
wp_dequeue_script( 'contact-form-script' );
}
}
add_action( 'wp_enqueue_scripts', 'my_deregister_scripts' );
- Audit your Tag Manager. Google Tag Manager containers often accumulate tags over time. Each tag that fires during page load adds a task to the main thread. Remove unused tags, set appropriate triggers (for example, fire marketing tags only on conversion pages), and use the Tag Manager's built-in timing reports to identify slow tags.
- Delay non-essential third-party scripts. Chat widgets, feedback tools, and social media embeds do not need to load immediately. Use
requestIdleCallback()or a scroll-based trigger to load them only when the user is likely to need them. For detailed strategies, read our guide on 14 methods to defer JavaScript.
React / Next.js
React and Next.js sites are primarily powered by JavaScript. Executing startup scripts, hydrating components, and processing the virtual DOM all take time and can cause input delay for the Interaction to Next Paint (INP). The good news is that both React and Next.js provide tools to manage this effectively.
- Use server components (React Server Components in Next.js App Router). Server components are rendered on the server and send zero JavaScript to the client, which directly reduces the amount of code competing for main thread time.
- Load third-party scripts with the correct
strategy. In Next.js, use the
next/scriptcomponent withstrategy="afterInteractive"for scripts needed after hydration, orstrategy="lazyOnload"for scripts that can load during browser idle time. See our async vs defer JavaScript guide for the underlying principles. - Implement an idle-until-urgent pattern. This pattern prioritizes user interactions
over background tasks by using
requestIdleCallback()for non-critical initialization while keeping a synchronous fallback that activates when the component is actually needed. - Lazy load components. Lazy load components that are not immediately needed using
React.lazy()or Next.jsdynamic()with{ ssr: false }for client-only components. - Use Suspense for interactive components. Wrap interactive components in
<Suspense>boundaries so that the rest of the page can render and become interactive while heavy components load in the background. This prevents a single slow component from blocking input processing across the entire page. - Use React transitions for non-urgent updates. Wrap non-critical state updates in
startTransition()so React can interrupt them if the user performs a new interaction. This keeps the UI responsive even when large re-renders are in progress.
Explore the other INP phases
Input delay is just one part of the Interaction to Next Paint. To fully optimize your INP scores, you should also address the other two phases:
- <b>Processing Time</b>: Optimize the event handler execution that accounts for approximately 40% of total INP time.
- <b>Presentation Delay</b>: Reduce the rendering and painting work that accounts for approximately 42% of total INP time.
For a complete diagnostic workflow, see our guide on how to find and fix INP issues, and return to the INP hub page for the full overview.
Pinpoint the route, device, and connection that fails.
CoreDash segments every metric by route, device class, browser, and connection type. Real time data. Not the 28 day average Google gives you.
Explore Segmentation
