Improve Interaction to Next Paint (INP)
Learn about Interaction to Next Paint (INP) and how to improve it
What is Interaction to Next Paint (INP)?
Interaction to Next Paint (INP) is a relatively new and exciting metric that measures the responsiveness of a webpage throughout all the interactions on a page. A low Interaction to Next Paint ensures that the page will be reliably responsive at all times. The INP will become a Core Web Vital in March 2024 when Google will replace the FID metric with the INP metric.
Table of Contents!
To calculate the Interaction to Next Paint metric all differences between each user interaction and the final presentation change on the page are saved. The highest number of all the interactions (or the 98th percentile) will be the final Interaction to Next Paint (INP) metric.
98th percentile or the worst INP?
INP is a metric that aims to represent a page's overall interaction latency by selecting one of the single longest interactions that occur when a user visits a page. For pages with less than 50 interactions in total, INP is the interaction with the worst latency. For pages with many interactions, INP is most often the 98th percentile of interaction latency.
How does Interaction to Next Paint (INP) work exactly?
An interaction happens when a visitor clicks or taps on a page. That interaction might result in a change in presentation on the screen. The Interaction to Next Paint (INP) measures the time between the click and the presentation.
A single interaction's latency consists of the single longest duration of any event that is part of the interaction, where the duration is measured from the point at which the user interacted with the page until the next frame is presented after all associated event handlers have executed. The duration is the sum of the following timespans:
What are good and bad values of the Interaction to Next Paint (INP)?
To pass the Core Web Vitals for the Interaction to Next paint metric the 75th percentile of page loads recorded in the field should stay below the 200ms:
- An INP below or at 200 milliseconds means that your page has good responsiveness.
- An INP between 200 and 500 milliseconds means that your page's responsiveness needs improvement.
- An INP above 500 milliseconds means that your page has poor responsiveness.
How to measure the Interaction to Next Paint (INP)?
The Interaction to Next Paint can only be measured with field tools. In order to measure the Interaction to Next Paint we need real user interaction. Google measures all the interaction that real chrome users have with a page and stores it in the CrUX dataset. The CrUX dataset is the official dataset for the Core Web Vitals.
Get the official INP metrics
You can get the official INP metrics in PageSpeed insights or the CrUX dashboard and Google BigQuery. PageSpeed insight will give you the 75th percentile score for the last 28 days. Google BigQuery (through datastudio) will give you more historic context.
Tracking the Interaction to Next Paint with Real User Monitoring
While the official CrUX dataset is the final source for Interaction to Next Paint metrics the CrUX dataset is not really usable because it is highly anonymized. The Crux dataset does not provide real-time monitoring nor does it allow much filtering. That is why Web Performance Consultants typically rely on Real User Monitoring.
Measure the Interaction to next paint of the current session.
The easiest way to debug the Interaction to Next Paint is through Lighthouse in 'timespan' mode. You could also use the Core Web Vitals Visualizer or if you are feeling hands-on with the Google Web Vitals JavaScript Library
Log the INP to the console with the Web Vitals JavaScript library
<script type="module"> import {onINP} from 'https://unpkg.com/web-vitals@3/dist/web-vitals.attribution.js?module'; onINP(console.log); </script>
How to improve the Interaction to Next Paint?
The interaction to Next Paint is a complicated metric. Your page might be really fast and respond instantly for the most part. Unfortunately if only one interaction is slow it will affect the entire Interaction to Next Paint.
Now remember, the INP can be broken down to the input delay, processing time and the presentation delay.
PageSpeed TIP: most of the time the INP will be much worse when a user interacts with the page during the startup stage of of page loading. That is why, when debugging the INP it makes sense to log all interactions as well as the page loading state!
1. Minimize the input delay - prevent long tasks on the main thread
Usually any page is less responsive during the page startup phase. That is when most main thread work is done (parsing, decoding, rendering and scripting). In order to keep the main thread af free as possible consider:
- Remove unused code. This can be done though a process called tree shaking (removing unused code) and code splitting (bundling your code in a way so that it's grouped into many small bundles that can be loaded as they are needed).
- Load non-essential code during browser idle. For example, do you really need a chat widget during the first 500ms of page load? No, probably not!
- Identify slow scripts that require a lot of resources and rewrite the code to make it more efficient.
- Make sure your page is 'easy to render'. Avoid large DOM sizes, too many or huge images, too many video's CSS animations etc
2. Minimize the processing time - provide immediate feedback to ensure the page responds directly to user input
When a visitor performs an action like sending a form, or adding a shopping item to a basket do not wait for the server-side confirmation (your form has been sent, your items have been added to the basket) but provide immediate feedback (we are sending your form, adding itemX to basket).
Also yield to the main thread as soon as possible. Because JavaScript does this thing that is called 'run to completion' it will block the main thread until all the code has been executed. You can manually create a break point where the browser can update the layout (and then continue the rest of the code) by 'yielding to the main thread.' The easiest way to do this is by wrapping parts of the code into a setTimeout()
const formfeedbackEl = document.getElementById("formfeedback"); const formEl = document.getElementById("form"); formEl.addEventListener("submit", (evt) => { evt.preventDefault(); formfeedbackEl.innerText = "Submitting form ... please hold on"; let headers = new Headers({ Accept: "application/json" }); let formData = new FormData(formEl); fetch("/form-endpoint", { method: "POST", headers, body: formData }) .then(function (response) { return response.json(); }) .then(function (jsonData) { formEl.reset(); formfeedbackEl.innerText = jsonData.message; }); setTimeout(other_code_that_needs_to_run(),0); });
3. Minimize presentation delay - keep things simple!
1. Keep the DOM small and simple. Basically it will be much easier for a browser to render a page with less DOM elements (html nodes) then it will be for a browser to render a page with lots of nested and complicated DOM nodes.
2. Use content-visibility to lazy-render off-screen content. Content-visibility will speed up rendering of visible parts of the page by delaying rendering of off screen content by rendering that off scree content just-in-time.
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