What is Interaction to Next Paint (INP) and Why is it important for FE dev?
Tags: webdev, javascript, webvital, frontend
Published: 2024-05-31 05:43:18

Hello Folks!

As a front-end developer, the term **[web vitals](https://web.dev/articles/vitals)** has become a buzzword in my field. This topic has been brought up in almost every interview I've had, and my tech leads often discuss the importance of improving these web vitals during our daily development meetings.

So, What are Web vitals?

The term `web vitals` sounds like the vitamins for a website. Just as a healthy human body should have good vitamin levels, a website with good web vitals reports indicates that the website has good performance.

Web vitals are a set of parameters that help us to measure the performance of a website. They provide a comprehensive assessment of the user experience by evaluating various aspects of a website's performance, such as loading speed(`LCP`), interactivity(`INP/FID`), and visual stability(`CLS`).

The current set of Core Web Vitals focuses on three aspects-

- Largest Contentful Paint ([LCP](https://web.dev/articles/lcp)): measures loading performance

- Interaction to Next Paint ([INP](https://web.dev/articles/inp)): measures interactivity

- Cumulative Layout Shift ([CLS](https://web.dev/articles/cls)): measures visual stability.

Like our Vitamins have to be at a certain level, similarly these web vitals also have a threshold to justify whether a metric is good or bad.

-  `LCP` must occur within 2.5 seconds of when the page first starts loading

-  To provide a good user experience, pages must have an `INP`of 200 milliseconds or less.

- To provide a good user experience, pages must maintain a `CLS` of 0.1. or less.

![webvitals metrics](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u3m69acemfbdosowm0ow.png)


I hope now you have an idea about `Web Vitals`.

 
Let's focus on **INP**, which is a new member of the web vitals family.


###What is INP?

Interaction to Next Paint (INP) is a key metric in web performance optimization that measures the time it takes for a web page to respond visually after a user interaction. It focuses on the delay between a user's action and the subsequent visual feedback on the screen, providing insights into the responsiveness of a web page.

It basically means you are doing some interaction with the webpage like clicking on a button or typing in the input box. Hence the webpage has to paint something instantly(_within 200ms_) on the screen after your interaction.

![INP exmaple](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gq8kka4t3xtfpdm1papv.gif)

> Imagine you are on a website and click a "Submit" button to place an order. Behind the scenes, an asynchronous process, such as an API call to confirm the order, is initiated. However, as a user, you do not see any immediate visual feedback on the page to indicate that your action has been acknowledged.


![Poor INP](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tuaw7kqfk033rntzo89x.gif)

Now, let's enhance this scenario with **Interaction to Next Paint** (INP) in mind. After clicking the "Submit" button, the button instantly displays a loading spinner or a ripple effect, providing you with immediate visual feedback that your order is being processed. This visual cue not only acknowledges your action but also assures you that the system is actively working on your request, enhancing the overall user experience by reducing uncertainty and improving perceived responsiveness.

![Good INP](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/euh948kp8jbikcdhyszp.gif)


###How to measure INP?

To measure interaction next paint. First, we need to understand the interaction cycle.


![Interaction lifecycle](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/unp5dwf54fxunwlfucvg.png)

Every interaction in a browser can be broken down into three distinct phases:

1. **User Interaction**: This is the initial phase where you, as the user, engage with the interface by clicking on a "View Details" button, triggering an action on the webpage.

2. **Processing**: In this phase, the browser's CPU processes your interaction, executing the necessary tasks such as fetching product data from a server, handling any calculations, running scripts to fulfil the requested action or waiting for any background task to be complete.

3. **Presenting Data**: Once the processing phase is complete, the browser then renders the outcome of your interaction on the screen. This could involve displaying the product details you requested, updating the page content, or showing any visual feedback to indicate that the action has been successfully executed. 
 
All the above phases need time to happen. So these times can be considered as:

- **Input Delay**: the time between user interaction and the time the browser can process the event. There can be a possibility of more delay when a task is already running in the background.

- **Processing Delay**: the time it takes the browser to process the event handlers. This can consist of executing all functions of the call stack and any other async task.


- **Presentational Delay**: the time it takes the browser to recalculate the layout and paint the pixels to the screen. 

Let's dive into the browser and see what happens behind the scenes.

As we know the browser performs all tasks on the main thread.


![INP execution](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6gkr768cxlbcba0ywf9h.png)

The above image is a representation of the browser's main thread while the user interacts with the web page.

When the user started interacting there was already a long task or say a previous function call was in process.

Since the main thread is single-threaded, it waits for the current task to complete before processing the user's event. The time between the user's input and the start of the event handler's execution is known as the `input delay`.

Once the previous task is finished, the main thread starts executing the event handler's callback function. The time taken by all the synchronous operations performed within the event handler is called the `processing delay`.

After the event handler's execution is complete, the main thread recalculates the layout and hands over the responsibility to the compositor thread. The compositor thread creates layers, rasterizes the new UI, and sends the final frame to the UI thread for rendering on the screen. The time taken for these tasks is known as the `presentation delay`.

---

Hmm... we have come so far, now you must have gotten insights into INP. Let's see how we measure this in real-time project

There are many ways we measure the INP in our projects, I have mentioned some methods below—

1. Chrome Devtools: 

- Chrome provides a [performance tab](https://developer.chrome.com/docs/devtools/performance/reference#:~:text=Click%20the%20Performance%20tab%20in%20DevTools.&text=Interact%20with%20the%20page.,click%20Stop%20to%20stop%20recording.) to analyse a lot of things, inside this tab we can measure the INP time for every interaction.
 
{% embed https://player.vimeo.com/video/946563499?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479 %}
 
I started the performance recording in the above video and clicked the filter button. This interaction was recorded in performance analysis and after zooming to the pointer event under interactions accordion we can see our metrics 

 `Input delay: 2ms`
 `Processing time: 11ms`
 `Presentation delay: 19ms`
 `INP time: 32ms`

It is a good INP score for this event.

You can do CPU throttling in the same performance tab to emulate the performance in different devices.


- Chrome also provides the [Lighthouse](https://developer.chrome.com/blog/inp-tools-2022) to measure INP metric for specifics intercations. Select the Timespan option in the Lighthouse and perform interactions on the webpage.

 {% embed https://player.vimeo.com/video/947995694?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479 %}


As you can see in the above video I have done a couple of interactions, The Lighthouse has shown the INP metric of 60ms.
This 60ms is the highest time taken by any of those interactions.


2. [Web Vital](https://www.npmjs.com/package/web-vitals) JS Library

This npm module can be used to calculate web vital programmatically. Integration of this module can help you track INP on your webpage which you can store to analyse further to improve user experience. 
 
In the index.js(main) file write the below code to measure INP from this module.

```
//import onInp function on top of your file
import { onINP} from 'web-vitals';

//call this function and pass the callback function
onINP(console.log);
```

`onINP` function accepts a callback function, this function can be a simple console.log or any other function which will use data given by `onInp` for analytics purposes.

 The data object that `onINP` function provides is:

```
{
    "name": "INP", // web-vital metric
    "value": 64, // INP value
    "rating": "good", // rating according to score
    "delta": -8, // change from previous scrore
    "entries": [
        {
            "name": "pointerdown", // event type
            "entryType": "event",
            "startTime": 128389, // start time
            "duration": 64, // total duration of event
            "processingStart": 128389.60000002384,
            "processingEnd": 128407.19999992847,
            "cancelable": true,
             "target":"buttonElement" //  element caused INP
        }
    ],
    "id": "v3-1716124847453-6103318753137", // unique id to event
    "navigationType": "reload"
}
```

![INP using web-vitals](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5l5kj5os2493m2l1dkod.png)


This object can provide you with details regarding the event which caused INP. onINP function does not call the callback function on every event; it will invoke only when INP score changes. [Read more](https://www.npmjs.com/package/web-vitals#report-the-value-on-every-change) if you want otherwise.


<u>web-vitals</u> module uses [Performace Observer](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver/observe) internally. So, invoking `onInp ` function again & again will not be a good practice.


> [Create React App](https://create-react-app.dev/docs/measuring-performance/) also provides web-vitals implementation by default.



3. Other Tools

Many other third-party tools are available to measure INP scores for Real User Monitoring. These tools can be used to regularly collect performance data from actual users, which is crucial for measuring INP

- [PageSpeed Insights](https://pagespeed.web.dev/)

- [DebugBear](https://www.debugbear.com/test/website-speed)

- [Vercel Speed Insight](https://vercel.com/docs/speed-insights)

These tools require your website URL to measure web vitals. They gather data from web engines or by just running lighthouse tests.


There are some Chrome extensions available to get web vitals metrics.



> _Note:_ The INP score is not an average score of all interactions whereas the INP score is measured when the user leaves the page by aggregating all interactions the user made with the page throughout the page’s lifetime and returning **the worst-measured score**


![INP scores](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v81u3pwwrwqu1tamem37.png)

The above image shows some sample interactions and their INP score. Hence, The highest-measured score throughout the page's lifespan was **120ms**, the total INP score will be 120.



I hope you understand how to measure the INP score for your webpage by using various methods. Go! start enhancing the user experience for your consumers.

---

### How to improve INP score?


 The main idea of optimising the INP score is to keep the browser's main thread available for user interaction to process.

So, we need to focus on optimising the Javascript optimisation. This task can be done by following best practices—

- **Code Splitting**, lazy load js files when actually in need.


- **Asynchronous Functions**, write async code for the long task or break the long task into small tasks.


- Implement throttling, and debouncing for continuous user inputs.


- Use **Performance Profiler** and observe the time taken by each function call during interactions. [Read more](https://web.dev/articles/manually-diagnose-slow-interactions-in-the-lab)


- **Web workers** can be used to divert expensive calculations on different threads. Check lower-end compatibility.

- Usage of **rerequestIdleCallback** API that can help improve INP scores by scheduling tasks to run when the browser is idle.


- Js **requestAnimationFrame** and CSS `will-change`, `transform` and `opacity ` can help to have smooth & non-blocking animations.
We can improve presentation delay by optimising the recalculation of styles, reflow layouts, and repainting the screen.


- Avoid using window alerts & prompts, they block the execution.


- Avoid using too many event listeners. Instead of attaching event listeners to individual elements, attaching them to a common parent or using it not top level and using `event.target` property to determine which child element interacted.


- Avoid using excessive run-time or local storage to avoid slowness in your app.


Hurray! We have learnt many ways to improve our INP score and now we can greatly enhance the overall user experience.


I believe if you have gone through the above blog you must now get clarity over Web vitals and especially about Interaction next paint. 


I hope you liked reading it
Check out my [LinkedIn](https://www.linkedin.com/in/utkarsh-gupta-032223147/) to follow me for more content like this.

Thanks for reading 😃✌️. Please comment down your suggestions or if you have any better way to measure the INP score.