Web Performance Experts Guide to Mastering Interaction to Next Paint (INP)

Summary: It’s March 12th, 2024, a big day in the web performance community! Today we see Interaction to Next Paint take its (rightful) place in the Core Web Vitals, replacing First Input Delay (FID) as the primary metric for measuring website responsiveness and interactivity. This comprehensive guide, which includes insights from 13 web performance specialists, will provide you with the knowledge and practical advice you need to master INP.

  • by Jordy Scholing, Karlijn Löwik, Roderik Derksen & Erwin Hofman
  • Published
  • Reading time ± 39 minutes
  • INP Core Web Vitals
Web Performance Experts Guide to Mastering Interaction to Next Paint (INP)

Table of Contents

What you'll learn

  • Understanding INP: Learn about what Interaction to Next paint is, how it works, and why it's important for a smooth user experience.
  • Typical INP offenders: Discover the major factors that impede INP and slow user interactions on your website, like JavaScript.
  • Measuring INP: Learn about the tools and methods that can be used to measure INP correctly and find places where it can be improved.
  • Tips and tricks from experts: Some of the best web performance experts in the world have put together a list of strategies you can use right away to improve your INP.

Why would you want to improve INP?

The main goal should be clear: you want people who visit your site to be happy. A slow response time to user actions may cause your users to doubt the functionality of your website. For example, if an item in their shopping basket does not update quickly, or if a form field they are attempting to fill out does not provide the desired visual feedback.

Less frustrated users = increased conversions, giving you better performance than your competitors and improved page experience for SEO.

Wonder why improved Core Web Vitals are a good investment? Allow us to share 10 reasons!

Understanding Interaction to Next Paint

Interaction to Next Paint (INP) measures how much time it takes for a user to see a visual change on the page after they initiate an action.

An interesting fact is that INP is measured over the whole page cycle because these frustrations to users can hinder them over the whole page cycle as well. In fact: most INPs get reported after a visitor has been on your page for over 10 seconds.

If you want to improve your Interaction to Next Paint, it’s important to understand why it’s happening and what the main culprits are.

What is the starting point of your Interaction to Next Paint?

With free data we can get through Google's CrUX, several parties have built a free tool to retrieve it. As RUMvision, we have one that retrieves your historical Core Web Vitals data. Enter your URL and get to see what your INP score looked like over the last 6 months.

Check your Interaction to Next Paint

Enter the URL of your website (for example, https://www.google.com) to get the aggregated Core Web Vitals data for the last six months for all pages or specific URL's if they have enough traffic.

Alternatively, you can install the Core Web Vitals history extension, to get Core Web Vitals data of the site you're currently on!

Why is it called Interaction to Next Paint?

The first part of the name, "interaction," pretty much says it all. The INP sets out to measure the responsiveness or interactivity of a page. Here in the web community, we define an interaction as a user-initiated action. Some examples of what gets measured in INP:

Possible user actions that get measured as INP:

  • click or (on touch screens) tap, for example, to collapse an FAQ
  • slide out a navigation menu
  • add a product to your cart

These events aren't measured:

  • scrolling
  • hovering

As a result of this user action, the browser must now get to work and display the new content you requested as part of that interaction. The section labeled "To Next Paint" is this one. The processing time is also a critical intermediate moment. Here we have a visual representation of an INP event:

example of the interaction to next paint

Understanding the 3 phases of Interaction Latency

We can break down an interaction into 3 phases.

  1. The input delay, which starts when the user initiates an interaction with the page and ends when the event callbacks for the interaction begin to run.
  2. The processing time, which consists of the time it takes for event callbacks to run to completion.
  3. The presentation delay, which is the time it takes for the browser to present the next frame which contains the visual result of the interaction.

The total interaction latency is calculated by adding these three phases together. Every phase of an interaction contributes some amount of time to total interaction latency, so it's critical to understand how to optimize each component of the interaction so that it takes as little time as possible.

INP breakdownThe life of an interaction. An input delay occurs until event handlers begin running, which may be caused by factors such as long tasks on the main thread. The interaction's event handlers then run, and a delay occurs before the next frame is presented, as explained by web. dev

Understanding how a browser works is vital to preventing poor INP

We can split up the issues within an INP into 2 main causes, that prevent the browser from performing at optimal speed in responsiveness and hindering your users’ experience:

  1. JavaScript: often the main cause
  2. Rendering delays: not to be overlooked

You’ll see tips on how to improve both in the expert tips in this article. Just to give you a brief introduction into why these are an issue, it’s important to understand how a browser works.

A browser is constantly working to show you the most recent version of the webpage at the exact point where you are. It tries to update the page frequently, up to 60 times per second, to give visitors the impression that everything is running smoothly.

To get a better understanding of this watch Jake Archibald's genius demonstration on the web browser event loop.

Browsers could be prevented from achieving or rendering 60 frames per second. The main reason is JavaScript. As JavaScript's main job is providing interactivity, it’s not surprising that it’s often involved with issues in interactivity.

JavaScript's run-to-completion nature and the challenge it brings

As we see explained in the web browser event loop, a browser will wait for the JavaScript files to be compiled, parsed, and executed before moving on to rendering (painting) the rest of the page.

And it doesn’t always matter if you’ve got multiple code-splitted JavaScript files or one big bundle. Both have the potential to cause a delay. Or maybe even multiple within the one-page visit. It all depends on the amount of work a task is triggering.

It might not always be a UX risk, but it will when such a task either takes place during interaction, or a long task is triggered as the result of user interaction. The challenge here is that browsers try to be performant by batching JavaScript tasks together instead of updating the screen on every single JavaScript task.

That’s a good thing, but as paints are delayed until batched JavaScript tasks are done, it becomes easy to understand how and why a new paint -and the most noticeable and thus important part for your typical visitor- can be delayed.

The main thread is where this all happens. And this is why you’ll see in this article a lot of tips regarding the optimizing of JavaScript and being smart with it.

Browsers are just like men, they can't multitask. And this is often the main issue in a slow INP. Quote by Karlijn Löwik, CEO at RUMvision

What is the main thread, and why is it so important to INP?

Every web browser, including Chrome, Firefox, and Safari, has a main thread. This handles most of the browser's work, including displaying web pages, running scripts, and handling user interactions.

The main thread starts when you enter a URL in your browser. Parsing the webpage's HTML code creates a structured document object model (DOM) that reflects its content and structure. But its work continues. The main thread converts the DOM into pixels to render text, graphics, and animations.

The main thread covers interactivity and reactivity. When you click a link, fill out a form, or browse around a page, the main thread processes these events to keep the webpage responsive. Additionally, it runs JavaScript, which adds dynamic content and interactive elements to websites. The main thread runs JavaScript code, whether it's an animation or a web app.

More information about the main thread can be found here.

Understanding tasks, long tasks, and long animation frames (LoAF)

To gain a better understanding of the performance tips and insights presented in this article, you should be familiar with the concepts of a task, long task, and long animation frames.

What is a task?

A task is any discrete piece of work that the browser does. Tasks involve work such as rendering, parsing HTML and CSS, running the JavaScript code you write, and other things you may not have direct control over. Of all of this, the JavaScript you write and deploy to the web is a major source of tasks.
Task happens over the whole page cycle, but issues happen most often in the first loading of the page.

A depiction of a task kicked off by a click event handler in the performance profiler in Chrome DevTools. source: https://web.dev/articles/optimize-long-tasks#what_is_a_task
A depiction of a task kicked off by a click event handler in the performance profiler in Chrome DevTools. Source.

What is a long task?

The main thread is only capable of processing one task at a time. Long tasks are those that last longer than 50 milliseconds.

Long tasks are likely to cause responsiveness issues and poor INP. If a user tries to interact with a page—for example, click a button, or open a menu—but the main thread is already dealing with a long task, then the user's interaction is delayed waiting for that task to be completed.

This is why you want to break up long tasks.

example of long task, inp

What are Long Animation Frames/ LoAF:

Long Animation Frames (LoAF) is a great new diagnostic tool/ API from the Chrome web performance team that's currently in Origin Trial but will be shipped in Chrome 123. It focuses on identifying long animation frames that might delay user interactions or make the page feel sluggish.

  • Frame-based approach: LoAF focuses on long animation frames (rendering updates exceeding 50 milliseconds), providing a more comprehensive view.
  • Detailed breakdown: It offers detailed breakdowns of the frame duration, including style and layout time, script execution time, etc.
  • Better attribution: LoAF provides script attribution with details like invoker (how the script was called), source URL, and character position, allowing for precise identification of the culprit.

We will talk more about LoAf and how to measure it below.

Barry Pollard "Have you had a look at LoAF yet? A great way to track down the long-running JavaScript issues on your site in the field.Source: Barry Pollard via Linkedin

What is a good INP score?

According to Google's Core Web Vitals, a good INP is 200ms or less on the 75th percentile. More than 500ms is considered poor. Although it does account for outliers, the worst 2% of user experiences with events or interactions on your page are not included in this report. If you would like to learn more about this, you can find a detailed explanation in Google's documentation.

Google's INP threshold

One of the experts in this blog, Erwin Hofman, actually tried to bribe Web Performance Developer Advocate on Google Chrome’s Barry Pollard to extend it to 400ms, with Dutch Licorice, but his attempts failed
 We’ll get 'em next time 😀.

erwin hofman and barry pollard at fosdem

Let's try to bribe a Google employee...

Erwin Hofman and Barry Pollard attended Fosdem in Brussels earlier this year. The licorice bribery, while pleasant, was insufficient to increase the INP benchmark for up to 400ms.

Mission failed.

Why INP is the coolest perf metric

Brian Louis Ramirez Web Performance Engineer at Speed Kit

INP is the most challenging yet rewarding Core Web Vital to debug and optimize because it's a microcosm of performance optimization: Are we aware of what real users are experiencing — and what about those on slower, older devices? What work needs to be done first — and what tasks can be broken up and done later? Do we need all those animations — and if so, are we only animating performant properties when needed and avoiding JS to control or listen to them? Once the user interacts with the site, is it more important to process all that data to send to tracking than to update the UI — and who gets to decide that anyway? Do we know the performance impact of third-party code on our site — and do we have any better alternatives?

To optimize responsiveness as measured by INP, all people working on a website need to prioritze what matters most: the user.

Why is INP replacing FID?

INP tries to measure how quickly a page responds to someone interacting with it. It replaces FID and that's a good thing. One of the things we (SpeedCurve) noticed quite early on was that FID didn't seem to represent visitor experience very well – FID tended to be fast even when Total Blocking Time (TBT) was high whereas INP has a much stronger correlation with TBT.
- Andy Davies

Luckily for all of us, Google's performance team agreed that the value that FID gave us was limited. The fact that so many origins passed the FID said a lot:

  • 94.1% percent on mobile
  • 99.9% on desktop

This is why they worked hard to introduce a better, more complete way of measuring the interactivity and responsiveness of a page. Thus Interaction to Next Paint was born. It was introduced in May 2022, and already reported in the Web Vitals- a year later it was announced that it would be replacing FID, and this moment is now upon us. We as a community are very happy with this change, as you can’t improve what you can’t measure.

INP stable

So, when INP becomes a Core Web Vitals the passing rates will be as follows, as of January 2024:

  • 41,04% on mobile
  • 53,07% on desktop

For desktops, this is a minor deterioration of about 0,5%, but on mobile, it’s around 5% more origins that will not pass the Core Web Vitals anymore.

CrUX report, mobile data of all technologies included

CrUX report, mobile data of all technologies included

The reason that the pass rate for INP is a lot lower is that it measures more than just the first input delay, and people never really had to worry about an interactivity metric for passing the Core Web Vitals. As you can see on the timeline below FID was quite easy to pass from the beginning.

FID pass rate

Did Google introduce INP just to annoy us?

No, not at all! The main goal of improving the measurements of the Web Vitals API and libraries is to help you gain better insights about what's happening on your site in terms of performance. This is why they introduced Lighthouse, why the performance panel in DevTools is continuously improving, and that’s also why they moved on to CrUX and Core Web Vitals. They are continuously at work to improve the measurements and the solutions, so you have a toolset to help your end users improve their UX.

Just this last year, they’ve introduced awesome new features you can use, like LoAF, whiskers in the performance panel, soft navigations, and many more.

Why Real User Monitoring is the easiest way to find INP issues

It’s important to understand that Interaction to Next Paint is a field data metric. This means it gets measured based on real users' experiences on your website. It can’t be measured in a lab test, like Lighthouse.

Field data is the most reliable source of information about how actual users interact with your website. It brings to light issues that lab data alone may not reveal. While interactions can be simulated in lab-based tools, you won't be able to replicate every interaction in the lab in the same way that field users do. Gathering field data for Interaction to Next Paint (INP) is critical for understanding how responsive your page is to real users, and it contains clues for improving their experience even further.

Google’s own documentation suggests that ideally, you start your INP optimizing journey with Real User Monitoring (RUM), as being able to attribute INP to individual interactions reduces guesswork and wasted effort.

What you should collect in the field and why

When collecting INP data in the field, you'll want to capture the following to give context to why interactions were slow:

  • The INP value: This is the key piece of data you'll need to collect. The distribution of these values will determine whether the page meets the INP thresholds.
  • The element selector string responsible for the page's INP: Knowing a page's INP is good, but not good enough by itself. Without knowing what element was responsible for it, you'll be in the dark. By logging element selector strings, you’ll know exactly what elements are responsible for interactions.
  • The loading state of the page for the interaction that is the page's INP: When a page is loading, it's reasonable to assume that there's more main thread activity occurring that could result in higher interaction latency. During page load, there's HTML parsing, stylesheet parsing, and JavaScript evaluation and execution going on. Knowing whether an interaction has taken place during page load or afterward helps you to figure out if you need to optimize for faster startup so interactions have more room on the main thread to run quickly, or if the interaction responsible for the page's INP in itself is slow regardless.
  • The interaction's startTime: Logging the interaction's startTime lets you know exactly when the interaction occurred on the performance timeline.
  • The event type: The event type is good to know, as it will tell you whether the interaction was the result of a click, keypress, or other eligible event type. A user interaction may contain multiple callbacks and can help you pinpoint exactly which event callback in the interaction took the longest to run

While this all seems like a lot to consider, you don't have to reinvent the wheel to get there. Thankfully, this data is exposed in the web-vitals JavaScript library, and you'll learn how to gather it in the next section.

Measure interactions in the field with the web-vitals JavaScript library

The web-vitals JavaScript library is a great way to find slow interactions in the field, thanks in large part to its ability to provide attribution for what's causing them. INP can be collected in browsers that support the Event Timing API and its interactionId property.

What makes INP harder to fix compared to other Core Web Vitals?

Matt Zeunert, founder at Debugbear

Your Interaction to Next Paint score doesn’t just depend on how your website is built. It also depends on what page elements users are interacting with. Even if most of the UI elements on your site respond quickly you can still have poor INP if the parts of the UI that users most often interact with are unresponsive.

Free starting point for measuring INP

To improve INP you need to understand how users interact with your website and which of these interactions are slow. As a starting point, you might be able to identify slow pages via Google Search Console and manually test common interactions on these pages. You can also DebugBear’s INP Debugger to automatically test simple interactions on a page.

To really apply targeted optimizations to your website you need to collect real user data.

Google’s web-vitals.js library can tell you what elements your visitors are interacting with and what interactions are most likely to cause poor INP.

Commercial tools like RUMvision, SpeedCurve, and DebugBear make it easy to set up real user monitoring for your website. They help you identify user segments that are more or less impacted by slow responsiveness and let you drill down into specific interactions and understand what caused them to be slow.

What is the impact of third parties on the INP?

Erwin Hofman, Web Performance and CTO at RUMvision

Third-party scripts often get blamed for causing your poor Interaction to Next Paint (INP). They can be a factor in causing your site to have poor Interaction to the Next Paint-score. But to answer ”What is the impact of third parties on INP” I have to be more nuanced. So, let’s introduce an analogy. What’s the impact of food on an athlete?

In elite sports, athletes assess the impact of food, training, and other factors on their performance to consistently achieve the best results possible under the given conditions. All these factors measure into the result, they either help or have a negative impact, and they all play their role. But also: the best combination of these factors is different for every athlete.

We can approach third-party scripts similarly. An A/B test, analytics script, chatbot, or analyzing script may improve the result of optimizing your users’ journey. But, their code will also come with an INP impact. How large their impact is will also be determined by your audience's conditions and first-party code.

Remember: any impact is happening on the browser's main thread. When this occurs after the FCP metric, it poses a risk to the INP metric, depending on the duration of its tasks. And nowadays, a typical website has a lot of tasks going on.

In sports and diet, it may take some time to see a correlation between food intake and results. In Interaction to Next Paint, it is fairly simple these days to measure the impact of third-party scripts on your real users.

The new LoAF API is a game changer in this regard. It provides us with indisputable insights into what happens during each interaction and identifies the scripts causing the most significant delays. As an RUM engineer, I can use these insights to easily demonstrate that impact to you. Not only can we showcase the impact for each of your third-party vendors, but it also allows us to show you the amount of millisecond impact their script caused and where. That way, instead of guessing, you can know with certainty what your third-party vendor's script impact is and whether it's worth the potential INP slowdown.

Same as the athlete: it's all about optimizing for the best results. We want to minimize the negative impact of third parties on INP, while also keeping an eye on the big picture. The new LoAF API helps us measure this impact precisely, allowing you to choose the optimal scripts that deliver value without sacrificing responsiveness.

With the new loaf api, web performance analysis finally become more straightforward. And indisputable as you can track the impact in the field, with instant results when using a RUM solution.

What are third parties doing about their impact on INP?

Jordy Scholing, Web performance and customer success at RUMvision

The last thing third parties want to do is increase bloat or delays on your website. After all, they tend to have a function that aims to help you, whether it's an a/b test, a chatbot, a cookie consent banner, or a heatmap. Or an ad, which of course can also be the cause of an INP.

Just because third parties do not intend to harm your INP, doesn’t mean that they don’t. Be careful with what you add to your pages.

If we look at the third-party data from RUMvision, which is real-life data of all users INP with LoAF enabled in November 2023, we see a lot of issues.

Source: Analysis of INP performance using real-world RUMvision data by Rick Viscomi

We can see a lot of vendors in the healthy bucket, but also a lot in poor. So, how do they respond to that when you request their help improving that?

Well, it depends
 in my experience as head of customer success manager of RUMvision, I’ve helped a lot of merchants contact their third-party vendors. These signals are often taken seriously, for instance, we had this great win with Big Sur AI.

The steps that resulted in a use case were:

  1. The client reached out to the third-party vendor, armed with the real user data knowledge
  2. Based on these insights, the third-party vendor optimized their JavaScript
  3. We noticed the amount of involvement of their impact within INP issues starting to drop
  4. And quite significantly too as can be seen in the image below! Win for us all!

Screenshot from Elastic that shows Big Sur’s involvement in LoAF / INP over time via Erwin Hofman

On the other hand, there are instances when vendors refer to lab tests or FID documentation, where their influence seems minimal because they are unaware of what LoAF can help visualize. This is fine though, given that LoAF and INP data were unavailable at the time. But now that we have that to concentrate on, real user experiences can get better.

Convincing them of the validity of the real UX impact of INP is one of the reasons we as a community went out to write this article.

My advice is always, to just send them an email with what you see in your data. Chances are they are willing to improve their code based on that. And if they don’t, know that we offer a benchmark in RUMvision of their competitors, so you can choose the one with the lowest performance impact.

This is not to bother them, but as a RUM tool, we want our customers to be able to choose the best performing one on mainly INP.

It’s a team effort guys 😀

It is not only third parties that are impacting INP

Andy Davies, Speedcurve

Sometimes third parties are responsible for poor INP times (particularly in publishing) but in my experience, there are plenty of sites where they're not the problem so double check they are the source of high INP times before spending too much time on them. One thing I've noticed is that INP third-party tags are concerned about their impact on INP so they're much more receptive to sites asking them to improve, but if you've got a vendor that's not listening it becomes a business decision whether to continue using them or not.

What are common issues observed in 1st-party scripts that can lead to a high INP?

Sander van Surksum, page speed consultant and tech lead at Iron/Out

First-party scripts are designed to enrich the user experience, offering functionalities that range from interactive menus to dynamic content updates. Yet, their execution can sometimes bog down a website's responsiveness. This sluggishness is often due to scripts performing lengthy computations or heavy DOM manipulations, which monopolize the main thread, delaying the processing of user inputs.

One common problem in 1st-party Javascript that causes the website to respond slowly is trying to do too much at once, particularly with tracking and analytics events.

We often see functions that include code that is not relevant to the users. JavaScript's run-to-completion nature means that once a function starts executing, it must finish before the browser can process other tasks, including responding to user input. While collecting data is crucial for understanding user behavior, its synchronous execution can severely impact INP, as it forces the browser to complete these tasks before responding to further user interactions. So the best way to handle this is to debug those tasks and focus on what is necessary to fulfill the user needs and what can be delayed.

The recommended approach is to defer non-critical stuff to ensure that the main thread remains available to process user inputs promptly. You can improve the responsiveness by using setTimeout(0) and requestIdleCallback() to run tasks when the browser is idle or at the next available frame.

Alternatively, consider using modern techniques such as yielding, which allows prioritizing essential tasks for the main thread.

layout thrashingExample of layout thrashing

Another issue we see often is Layout thrashing, where extensive layout recalculations and style reflows occur due to DOM manipulations. This problem is exacerbated by complex CSS selectors, excessive CSS, or a large DOM tree, all of which can delay the browser's rendering process. Therefore it's always good to look at recalculation or repaints in your long tasks. Often these repaints and recalculate styles are the reason why a task is a long task.

We’ll discuss how to avoid layout thrashing and repaint in the performance experts tips section.

What if I can fix my INP and benefit the environment at the same time?

By Ines Akrap, Web Performance GDE and Solutions Engineer at Storyblok

As we already know, Interaction to Next Paint (INP) measures how much time it takes for a user to see a visual change on the page (“repetitio mater studiorum”). Most of the time that maps to the amount of JavaScript that has to execute on the site, both during loading and after the interaction. Working with clients coming from the world of traditional CMS for many years, I have noticed one common issue that is quite critical to achieving a good INP. Big Javascript bundles.

When working with CMS, we naturally have many different components, and depending on the size (and age) of the platform those components can sometimes be counted in hundreds. Each one of these components usually comes with its own CSS and JS. Due to legacy best practices coming from the era of http/1 protocol, I often encountered CSS and JS code of ALL the components being bundled together in one package, often leading to packages of over 1MB of code.

Why is this such a big issue?

Often there are few common components appearing on each page such as header, footer, menu, text and image, newsletter, etc. However, many others are features of a specific page, and due to this approach, included on every page and are used very rarely, if ever. Bundling all the JavaScript into one big script will cause the browser to dispatch one single task to evaluate it, and the bigger it is, the longer it will block the main thread, making it unavailable to react to any user input (especially on low-end devices). Since often the page is rendered (elements are visible) before it is loaded (page is interactive), there is quite a big chance that the user will start interacting with the page while the main thread is still busy with processing JS, which will introduce delays into interactions processing and result with bad INP score (and bad user experience).

Delivering only necessary code

Every aspect of web browsing requires electricity: from operating servers where resources are stored, through pushing every single byte through the Internet to reach its destination, to finally browser processing and rendering site by powering up the right pixels on screen. Worldwide, most of the electricity is still produced by burning fossil fuels, resulting in bigger CO2 emissions with bigger energy consumption.

Ines Akrap

Performance Expert tips to improve your INP

Now that we have captured a lot of basic and fat insights, you also want to know how the experts handle this metric and what strategies they have already experienced as successful.

Everyone who contributed to this article is a web performance specialist. Below, a few of the specialists have shared some tips on how to optimize INP.

Yielding to the main thread

By Jacob Groß

Coming to the next part, we’re taking a look into how we (developers or webmasters) can improve INP which is affected by long tasks caused by JavaScript execution. Fast INP is achieved by giving the browser paint opportunities, so the more often you yield, the fewer long tasks that keep the main thread busy, and the more chances the browser has to paint quickly after user input. Flipping this around: by doing less (or even nothing), you get great INP.

One way to achieve this is by splitting up work into multiple pieces with a small break in between. In terms of INP that means splitting up a long task into multiple smaller ones, plus giving the browser the chance to paint in between the smaller tasks. This is done by “yielding” to the main thread. So, how do you yield?

In all browsers, we can use setTimeout(fn, 0), which allows us to defer the execution of fn to a separate task. This achieves our goal of splitting up one big task into smaller ones.
On a page, where we have perfect control over all executing scripts, setTimeout is a good choice. However, most pages have 3rd party scripts (e.g. analytics/ads), where keeping full control is hard. Without going in-depth here, fn will be scheduled at the very end of the tasks queue, while tasks from competing sources could be moved to the start – this creates a potential dilemma, as fn might be delayed further and further. While this problem is not a problem you are guaranteed to experience by using `setTimeout`, scheduler. yield has been introduced to combat the described “queue jumping” by continuing the execution in order (available in Chromium):

scheduler.yield optimize long taskSource: web.dev

Let’s take a look at a simple example that reacts to some kind of click on a UI element where sendAnalytics is a slow function that executes a lot of JavaScript in one long task:

function handleClick() {
  updateUI();
  await scheduler.yield(); // <- added
  sendAnalytics();
}

With this one-line change, we make sure the expensive analytics call happens after anything that might be important to the user. You can of course also use setTimeout(sendAnalytics, 0) here instead.
One thing to be aware of is, if updateUI is slow, you might also get a bad INP. In that case, try breaking it into smaller tasks – or create a render opportunity for the browser by scheduling the UI update with the postTask API, like so: scheduler.postTask(updateUI, { priority: "user-blocking" }). You can of course also combine postTask, yield, and setTimeout where applicable. Last but not least, a sensible rule of thumb for determining when to yield is:

If a function call doesn’t provide visible feedback to the user, it is not urgent to the user. Run it after yielding.

Breaking up Long Tasks by "yielding to the main thread" is one way to improve INP but the browser is still expected to do the same amount of work – it's just broken up into smaller pieces. The danger with relying on just this approach is that we're "treating the symptom rather than the problem" and visitors that have slower devices or devices in low power modes will still suffer from slow interactions.
Andy Davies

Reducing the overall dependence on JavaScript

By Ryan Townsend

Whether you use React, Angular, Svelte, or any other JavaScript framework – the Web Platform can do so much for you. To put a number on it: I was able to cut a recent Next.js project down by 50,000 lines recently by better utilizing HTML, CSS, and other Web Platform APIs that come out of the box in browsers.

It's all too easy to form a habit of reaching for npm install by default, and can quickly lead to INP becoming a problem as your website fills with someone else's JavaScript.

Yes, anyone could absolutely write one single line of JavaScript which will destroy your INP. And yes, the extreme of going CSS-only isn't always a silver bullet – too much complexity in selectors and large DOMs can cause slow style recalculations, again destroying your INP.

If you can utilize native web platform functionality in a sensible way: Less Javascript (generally) means better performance.

The efforts of Interop, the pressure on Apple, and the evergreen nature of browsers mean that new native APIs are arriving at an unprecedented rate.

The amount of browser updates/ releases in 2009 vs now (2022)

Browser releases around 2009 vs. 2022, big difference.

This year we're already seeing movement on cross-browser support for View Transitions and the Navigation API, both of which help support that 'app-like' feel without the burden of Single Page Application frameworks.

Even if the available APIs can't take you all the way, they can act as building blocks that only require a light sprinkling of custom JavaScript. For example, a recent project needed to constrain some dialogs to only show one at once. There is support for this in the Popover API, but the platform doesn't have this for <dialog>

`. There are plenty of NPM libraries for modals supporting thousands of unnecessary features, but 458 bytes of simple JavaScript—loaded with low priority to not interfere with the critical rendering path—was all that was needed.

Frameworks and libraries come and go, but it's always worth investing your time in keeping up with advances to the Web Platform because features rarely get deprecated – you can depend on them moving forward and therefore it makes them a valuable asset to your career that is agnostic to any framework.

If I had to call out one such feature right now: read up on invokers, these let you interact with various elements in a declarative non-JavaScript manner using purely HTML. They are in Chrome behind a flag, the PR to test in WebKit has been merged and Firefox has shown positive support – in the meantime, there's even a well-maintained polyfill. Just think how much code for event handlers this will replace.

How to Avoid Layout Thrashing or Repaints

Sander van Surksum, page speed consultant and tech lead at Iron/Out

When you change things on a webpage with JavaScript, the browser usually waits to update everything until after your script is done. But, if you ask the browser about the size or position of an element while making changes, it has to be updated right away to give you an answer. This is called a "forced reflow."

Forced reflow is like measuring your room every time you move a piece of furniture. It's inefficient because you're constantly stopping to measure instead of moving everything first and measuring afterward.

"Layout thrashing" happens when you mix these updates and questions in a loop, making the browser recalculate the layout many times. It's like moving furniture and measuring the room over and over again, which slows everything down.

To avoid this, first do all your changes (the "sets"), and then ask your questions (the "gets"). This way, the browser updates the layout less often, making your webpage faster.

Here are more ways to make your website respond faster, especially with your own scripts:

  • Be careful with event handlers on the body or window. Every time someone does something on the page, these handlers kick in and can slow down how quickly the page reacts.
  • Use the CSS "content-visibility" property for content that's not immediately visible on the screen (Under the fold). This helps in controlling what will be rendered and not.
  • Keep your DOM size small, especially on Product Landing Pages (PLP).

Verifying INP improvement before deploying the FIX

By Tsvetan Stoychev, Currently at Akamai and creator of Basic RUM

One of the worst nightmares of a performance engineer is to work an a performance fix for weeks, to deploy a fix and to see no performance improvement or even worse, regressions.

And this brings me to something that gives me flashbacks from something I was tinkering with a few months back 


I was helping a customer investigate how INP could be improved. I wasn’t familiar with the codebase and to make things even more interesting, I wasn’t integrated with any of the customer’s dev teams. For sure I didn’t want to propose a solution that had no effect :)

I had to be creative and with the help of a debugger, a source code beautifier, and the Chrome’s Dev Tools Performance panel I was able to identify a few candidates that were causing high INP. Even better, with the help of Chrome Local Overrides, I was able to create my local version of the customer’s web application and verify that a performance fix works and doesn’t break functionality.

While running experiments I found myself in the cycle of overriding JavaScript and CSS files with Chrome Local Overrides and then 10 times - reloading a page, clicking on an element, measuring INP, noting the INP duration, and comparing results to previous experiments.

The process was interesting but it was becoming repetitive and time-consuming. I decided to invest a bit of time in exploring Puppeteer with the hope of saving time and eventually sharing a testing framework with my colleagues and the customer.

It took me a few days to learn and to build the INP testing framework based on Puppeteer but it was worth doing it. A lot of time was saved and I ended up with a framework that could be reused for other investigations.

We found that the use of getBoundingClientRect() was causing reflows. I shared the findings with the customer’s developers and as they knew their codebase best they suggested that it was possible getBoundingClientRect() to be substituted with IntersectionObserver.

The framework helped us to find out that the proposed solution could improve INP by ~29%.

INP puppeteerThe proposed solution was implemented and deployed by the customer’s engineers in the middle of November 2023 and in the following months we could see ~15% improvement in the Good INP score and ~28% reduction in the Poor INP score.

The framework allowed us to:

  • Click on an element to measure INP at a defined moment.
  • Run experiments with 4 times throttled CPU.
  • Override JavaScrip, CSS, and other assets to simulate INP fix.
  • Automatically accept Cookie Consent popups.
  • Simulate specific User-Agent and screen size.
  • Run the same experiment 10 times to reduce outliers.

inp in search console

If you are interested to learn more or to play with the framework:

The Importance of Optimizing Browser Rendering

As the Interaction to Next Paint (INP) metric is about to make its official entry into the Core Web Vitals, it's clear that it is often almost exclusively associated with issues related to JavaScript, and especially to third-party scripts. The execution of JavaScript upon interaction is, admittedly, one of the most CPU resource-intensive operations, and thus potentially a source of latency.

However, while the concept of Interactivity plays a key role in understanding and optimizing the INP metric, it should not overshadow the "Paint" aspect, which is one of the crucial steps in the rendering phase. This phase is preceded by two other steps, "Style" and "Layout," and followed by a "Compositing" step. It's this entire process that transforms CSS and HTML code into something visual.

js visual

Like any mathematical computation operation, the rendering phase also heavily relies on the CPU. In many cases, it can contribute to the emergence of Long Tasks and Blocking Time, which often results in an increase in INP in field data. This is why a focus must be placed on the structure of the pages, to ensure that the initial rendering is performed as quickly as possible and that recalculations upon interaction are minimized.

Fortunately, a growing number of native APIs have emerged in web browsers to address these issues. Here are a few that have proven effective in improving INP:

  • Using the CSS animations API whenever possible, to leverage the GPU rather than the CPU during intensive computation phases;
  • Simplifying the DOM structure of pages (number of DOM nodes and depth) and, if not possible, implementing lazy rendering and CSS containment;
  • Using the most concise and precise CSS selectors possible, and avoiding the use of the universal CSS selector (*), which is extremely costly in terms of rendering.

The approach is, in fact, broader than this, and involves ensuring that when defining or evolving the technical stack, the decision is based on concrete data on performance, accessibility, scalability, and resilience aspects. This is why I like to associate the work of the web performance expert with that of a quality manager. If this approach interests you, we detail it thoroughly in our article dedicated to improving INP.

When defining the technical stack, ensure decisions are based on concrete data on performance, accessibility, scalability, and resilience aspects.

Measuring Interaction to Next Paint by having the right insights

If you want to improve INP for your visitors I'd recommend analyzing the work that's triggered by the interaction to reduce JS execution, layout, and styling times. I've been helping sites improve their INP times and I wrote a detailed blog post on the approach I use to debug INP along with some recommendations on what I've found to be effective at improving it.

Most visitors will use a small number of common interactions - fix those and INP can improve dramatically.

Most visitors will use a small number of common interactions - fix those and INP can improve dramatically.

Understanding the geographic gaps in INP issues

By Jodie Chan, SVP of Product & Strategic Partnerships (Chinafy)

Don’t forget to remember regional variance when evaluating and improving your website with INP-based insights.

Countries like China present unique challenges to web performance due to limited network bandwidth, regulatory factors, and the behavior of third-party resources within their borders.

Consequently, even the best-designed websites may load excessively slowly (if not time out) and possibly not function from China.

Not all regions have the same average performance benchmark, tools, or experiences when it comes to website performance.When discussing INP in the context of China, this metric is mostly impacted by -

  1. Unoptimized script loading order. For example, if a script file is only loaded after a user interaction
  2. Reliance on China-incompatible API calls, such as a submission API that goes to an unresponsive domain (the reason may be because the domain is blocked or non-performant).

Most, if not all, of the solutions, however, lie in the architecture of the web app and/or scripts and not the performance of the web resources. That’s why it’s important for developers not to take the fast response time or a good INP score from a certain region (i.e., outside of China) for granted or as an average.

To address these regional variances:

  1. Test your site in different regions, subpar network conditions, and maybe even with 3rd party resource domains intentionally blocked to preempt potential user experiences.
  2. Consider that the weight attributed to each component of INP (input delay, processing time, and presentation delay) might vary depending on the end user's geographical location.
  3. This is where a conversation with the business stakeholder might have to take place so that the website doesn’t just “perform” well according to the latest metrics like INP but for the purposes for which the website was built.

What I appreciate about Google and its continued quest for better user metrics is that it keeps real users at the heart of the design of these metrics. INP, unlike FID, is a reminder that "you are only as strong as your weakest performing interaction," not just the first.

Looking forward, I'd be curious about the differences and insights that come from comparing FID vs INP and whether this new metric will unveil region-based insights. Are users' first interactions, and therefore revealed FID metric with a website more or less the same globally? Will INP reveal differences in regional behavior and therefore, regional differences in website interactive pain points?

Regional differences for INP example

In our RUMvision data, we’re able to get a geographical overview of the Core Web Vitals. In this screenshot, we’re looking at a website with international traffic. The experience for the INP metric differs a lot based on location. Think about what Jodie just mentioned, but also wealth.

No one better than Alex Russel can write about this with his yearly “The Performance Inequality Gap”.

inp experiences per country

The key to improving INP is persistence. In time, you can get your page's responsiveness to a place where users are happy with the experience you're providing them. The chances are also good that as you develop new features for your users, you may need to go through the same process in optimizing interactions specific to them. It will take time and effort, but it's time and effort well spent.

Google

Thanks for contributing

We as a performance community welcome the change from FID to INP, as better measurements for interactivity and responsiveness help you get better insights into your user's real experiences.

We hope that after reading this article, you feel better informed about the challenges- but more importantly - possible solutions to improve Interaction to Next Paint. And if you still have questions, know that there's a whole community happy to help you.

As Jordy said: it’s a team effort, guys! 😄

We at RUMvision want to thank all our contributors for their time, effort, and expertise. It's truly very awesome and much appreciated:

  • Brian Louis Ramirez
  • Andy Davies
  • Matt Zeunert
  • Sander van Surksum
  • Ines Akrap
  • Jacob Groß
  • Ryan Townsend
  • Tsvetan Stoychev
  • Eroan Boyer
  • Jodie Chan

Share blog post