Loadzen

← All articles

Core Web Vitals7 min readReece Crowther

How to Fix INP (Interaction to Next Paint): A Practical Guide

INP replaced FID as a Core Web Vital in 2024. Here is what causes poor INP scores and how to diagnose and fix slow interactions on your site.

What is INP?

Interaction to Next Paint (INP) measures the delay between a user interaction — a click, tap, or keyboard input — and the next time the browser paints a visual response. It replaced First Input Delay (FID) as a Core Web Vital in March 2024.

Unlike FID, which only measured the first interaction on a page, INP captures the worst interaction across the entire page visit. This makes it a more complete picture of how responsive your page feels to real users.

Thresholds:

  • Good: 200ms or below
  • Needs improvement: 200–500ms
  • Poor: above 500ms

  • How INP is measured

    INP measures three phases:

    1. Input delay — time from when the user interacts to when the browser starts processing the event.

    2. Processing time — how long the event handler runs.

    3. Presentation delay — time from when the handler finishes to when the browser commits the next paint.

    The largest single interaction during a page visit becomes the INP score. If a user clicks a button and nothing happens for 600ms before the UI updates, that is a 600ms INP event — regardless of how responsive everything else was.


    Common causes of poor INP

    1. Long JavaScript tasks blocking the main thread

    The browser's main thread handles both JavaScript execution and rendering. If a JavaScript task runs for more than 50ms, it blocks everything else — including responding to user input.

    When a user clicks something while a long task is running, the browser cannot start the input handler until the task finishes. That wait becomes input delay.

    How to find long tasks:

    Open Chrome DevTools → Performance tab → record an interaction. Look for red bars marked "Long Task" in the Main thread lane. The task's duration and call stack are shown on hover.

    How to fix them:

  • Break long tasks into smaller chunks using setTimeout or the newer scheduler.postTask API.
  • Move non-UI work off the main thread using Web Workers.
  • Identify the specific function causing the long task and optimise it.
  • 2. Heavy event listeners

    Event listeners on scroll, mousemove, or resize that run expensive DOM operations on every event fire hundreds of times per second.

    Fix:

  • Debounce or throttle event listeners that trigger on continuous events.
  • Use passive: true on scroll and touch event listeners so the browser does not wait for them before scrolling.
  • ```js

    window.addEventListener('scroll', handler, { passive: true });

    ```

    3. Rendering large DOM trees

    A DOM with tens of thousands of nodes takes longer to recalculate layout and paint after any change. Interactions that modify the DOM trigger a cascade of layout, style, and paint work.

    Fix:

  • Use virtualisation for long lists. Libraries like TanStack Virtual render only the visible rows.
  • Remove hidden DOM nodes rather than hiding them with CSS.
  • Simplify component trees — avoid deeply nested wrappers that do not add semantic value.
  • 4. Synchronous DOM reads followed by writes

    Reading a DOM property (like offsetHeight) forces the browser to compute layout. If you then write to the DOM, the browser must recalculate layout again. Alternating reads and writes in a loop causes "layout thrashing."

    Fix:

  • Batch DOM reads together, then batch DOM writes.
  • Use the requestAnimationFrame API to schedule DOM writes at the correct point in the rendering pipeline.
  • 5. Third-party scripts running on the main thread

    Analytics, chat widgets, A/B testing tools, and ad scripts all compete for main thread time. If they run during a user interaction, they add to INP.

    Fix:

  • Audit which third-party scripts are loaded and how they affect main thread usage using the Performance tab.
  • Delay loading non-critical scripts until after the page is interactive.
  • Use Partytown to move third-party scripts off the main thread into a Web Worker.

  • How to check your INP score

    PageSpeed Insights shows INP in the Core Web Vitals section if your URL has data in the Chrome User Experience Report (CrUX). This is field data from real users.

    For pages with low traffic that do not have CrUX data, you can measure INP locally in Chrome DevTools by running the Web Vitals extension while interacting with the page.

    Run a free speed check with Loadzen to see your current Core Web Vitals including INP.

    Related guide

    Core Web Vitals Fix Guide →

    Keep reading

    Check your own site

    Run a free speed check with Loadzen and get a prioritized fix plan for your specific platform.

    Run free speed check