Interaction to Next Paint (INP)

The INP is a web performance metric that sheds light on a website’s responsiveness from a user’s perspective. In simpler terms it measures the delay between a user’s action, such as clicking a button or typing in a field, and the web page’s visual response to that action. A low INP indicates a website that feels fast and reacts quick\\ly to user input, enhancing the overall user experience.

Below is an example of a good responsive component and a bad responsive component.

The main cause of a poor INP is heavy JavaScript execution. Optimizing how JavaScript parses, compiles, and executes on your web page will directly reduce INP.

We would need to perform following operations:

  • Clean up or reduce Javascripts on the page
  • Do the code splitting and load Javascripts conditionally only where they are needed.
  • Load Javascripts by using defer attribute, you can use async if the javascript is needed to be loaded early.

Possible Solutions

1. Code splitting

Common javascript files that are getting loaded on all pages may not be utilized or executed. Some pages would need it some pages might not. Instead of concatenating all Javascripts into one file and loading them on all pages. Try splitting the codes based on conditions and for the pages or modules it is needed for.

For example:

Lets say you have one big javascript file main.js and you have slider only on homepage, in this case you can split the main.js javascript into two files, such as main.js and slider.js. Here main.js can be used for common javascript that is required on all pages and slider.js can be only loaded if the page is homepage.

2. Reduce unwanted Javascripts

This is very simple to do as it involves only checks for javascripts in use or not. Some vendor libraries or third-party libraries might not be needed at all but it will affect the page speed score. So you can identify the files and remove them.

Also, there can be many unwanted javascript code execution on some pages. You can use code coverage tool in chrome to find out which codes are actually executing and which are not required for a certain page.

You can learn more about code coverage tool here – https://developer.chrome.com/docs/devtools/coverage/

3. Debouncing/display small CSS loading animations

For SPAs with search bars, that makes API calls to display search results, implement small loading animations with CSS (search loading animations CSS, there is a W3schools article) to provide visual feedback to the user.

4. Use FastDOM to avoid layout re-flows

FastDOM is a JavaScript library designed to optimize the performance of DOM manipulation and layout operations. It provides a way to batch and schedule DOM read and write operations to minimize browser reflows and repaints, ultimately improving the responsiveness and perceived speed of web applications. FastDOM schedules DOM operations asynchronously using requestAnimationFrame. FastDOM collects multiple DOM manipulation tasks and queues them for execution within a single animation frame. This batching process allows FastDOM to consolidate multiple DOM reads and writes into a single batch, reducing overhead and improving performance. This synchronisation helps avoid forced synchronous layouts and ensures a smooth user experience.

Here is a list of methods and properties that can cause layout reflows.

5. Loading scripts with dynamic imports

In contrast to static import statements, which must be placed at the top of an ES module, dynamic import() calls offer more flexibility by allowing developers to load chunks of JavaScript on demand from any part of the script. This versatility presents two significant advantages:-

  • By deferring the loading of modules until they are needed, dynamic import() calls help alleviate main thread contention during the initial page load. This is particularly beneficial for larger applications with numerous modules, as it prevents the main thread from becoming overwhelmed with compilation and evaluation tasks all at once. Instead, modules are loaded asynchronously as they are required, allowing the main thread to focus on critical tasks such as rendering the user interface.
  • Each dynamic import() call initiates a separate task for the compilation and evaluation of the imported module. This separation of tasks ensures that the main thread remains responsive and can handle other user interactions while modules are being loaded and executed.

6. Harnessing Web Workers

We had amazing INP gains when we started to leverage web workers to offload tasks from the main thread, enabling parallel execution and a more responsive user experience. By delegating certain tasks to separate threads, the main thread remains agile and responsive to user interactions.

A detailed guide about usage of web workers can be found here.

7. Lazy load below the fold elements:

Lazy loading below-the-fold elements is a technique used to defer the loading of images, iframes, or other resources that are not immediately visible when a user first loads a web page. This helps improve initial page load performance by reducing the amount of data transferred and speeding up rendering. Use the Intersection Observer API to monitor when the below-the-fold elements come into view. Intersection Observer allows you to efficiently track the visibility of elements relative to the viewport.

8. Reduce DOM size:

Minimize the nesting depth of DOM elements. Deeply nested structures can increase rendering and layout times. Flatten your DOM hierarchy whenever possible. Regularly audit your DOM structure and remove any elements or scripts that are no longer necessary. Unused elements contribute to DOM bloat and increase processing time. Minimize the use of inline styles and scripts. Instead, use external stylesheets and scripts to cache resources and reduce the size of the initial HTML payload.

A detailed reference is given here.

9. Using CSS solutions:

Replacing JS based interactive events with simpler HTML and CSS alternatives. A prominent use case can be of using a collapsable hamburger menu which is primarily done using the click event in JS. It can easily be replicated using a checkbox input and CSS attribute to trigger the menu action. A simple reference is linked here. This solution utilizes the checked pseudo class of input element to trigger the collapse action.

Other resources to learn INP optimisation

Above mentioned are some of the methods that can be used to optimise INP issues in a webpage. A detailed guide can be found here.

Other notable references:

Quizzes