Interaction to Next Paint - Input Delay
Learn how to find and improve INP issues caused by input delays
Interaction to Next Paint (INP) issues cause by input delay
In our previous article we talked about the interaction to next paint on how to identify interaction to next paint issues. If you would like to read up on the basics this is a great place to start!
In this article I will focus on 'Input Delay'. How this affects the Interaction To Next Paint issues and then explain how to minimize input delays to improve the interaction to next paint.!
INP TIP: most of the time the times input delay will occur during the early loading stages of the webpage!
Table of Contents!
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 (e.g., clicking a button or pressing a key). While there is always some input delay (even browsers need time to schedule the callbacks), input delay occurs when the browser is busy performing other scheduled tasks and cannot immediately schedule the callbacks requested by the interaction.
Input delay and the INP
The Interaction to Newt Paint (INP) can be broken down into 3 sub-part: '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'. For those that do not know: The Interaction to Next Paint is the successor of the retired 'First Input Delay'. The First input delay measured the time between the first interaction and the event callback. Even though the First Input Delay 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.
The importance of input delay
Since many developers think about improving the INP in terms of optimizing callback function (optimizing the process time) the 'Input Delay' is often overlooked. Granted, Input Delay is not usually the biggest part of the INP but nevertheless, if we optimize the INP delay we will often optimize all INP interactions at once!
At CoreDash we collect millions of core web vitals data point each hour. Based on that data the Input Delay accounts for just 18% of the Interaction to Next Paint. And while that is not nearly as much as the Presentation Delay or the Processing time it is still a significant portion.
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 asynced scripts that are enqueued early on will create early tasks
- 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.onload
event or scripts that get delayed by so-called optimization plugins. - Repeat tasks. Recurring tasks via
setInterval()
that take a relatively long time to execute an 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.
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. So break up long tasks with
scheduler.yield()
(experimental) 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's functional.
- Idle Time Script Execution: Schedule non-critical scripts to run during browser idle periods with
requestIdleCallback()
. RequestIdleCallback 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 Script to run off the main thread. This will prevent the main thread from blocking and cause INP input delay issues.
- Check for input pending during repeat tasks. Before executing a set or 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 scripts because each line of code can potentially cause an input delay that affects the interaction to next paint.
async function yieldToMain() { if ('scheduler' in window && 'yield' in window.scheduler) { return await window.scheduler.yield(); } return new Promise((resolve) => { setTimeout(resolve, 0); }); }
Practical Implications
Let's get to the most important question: 'What does this all mean for my site'. Let's break it down for WordPress & REACT.
WordPress
WordPress, due to it's nature, 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 we have no control over the contents. This means that we cannot change the files and optimize 'bad code'. Even if the scripts behave nicely there is no guarantee that they will do so in the future.
So in order to minimize input delay and optimize the Interaction to Next Paint (INP) do the following:
- 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?
- Choose Lightweight Themes. Many WordPress themes 'offer everything'. While that seems like a great idea it means that they likely are 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 a user-friendly, visual interface for building layouts. Unfortunately they often rely on scripts for presenting that lay-out to the visitors.
- Only load scripts when they are needed. WordPress has a tendency to load all scripts on all pages. To fix this simply create a child theme and unregister unneeded scripts per page type. For example:
function my_deregister_scripts() { if ( ! is_page( 'contact' ) ) { // Example: Deregister contact form script on non-contact pages wp_dequeue_script( 'contact-form-script' ); } } add_action( 'wp_enqueue_scripts', 'my_deregister_scripts' );
REACT / NextJS
React of NextJS sites are mostly powered by JavaScript. Executing these scripts will take time and cause in input delay for the Interaction to Next Paint (INP)
- Use server components. Server components are rendered on the server and not on the client which will lead to a reduced amount of JavaScript
- Load third party scripts with the correct strategy. Load third party scripts after hydration of even during the browsers idle time
- Implement an idle until urgent pattern: This pattern prioritizes user interactions over background tasks and creates temporary states while the browser uses requestIdleCallback to perform non-critical tasks during browser idle periods.
- Lazy load components. Lazy load components that are not immediately needed using
React.lazy()
or NextJSdynamic()
- Use suspense for interactive components. Consider only client side rendering interactive components that need hydration to become interactive.
Stop Guessing, Start Measuring
I use Core/Dash to optimize my clients sites. So Should You.
- Easy set up.
- Over 5000 happy clients
- Free trial, No strings attached