Interaction to Next Paint (INP) is the Core Web Vital for responsiveness. It measures the delay between a user interaction (a click, tap or key press) and the next time the screen updates. A good INP is 200 milliseconds or less for most visits.

Poor INP feels like a sluggish, unresponsive page, and it affects how search engines assess page experience.

What makes up an interaction

Every interaction has three parts:

  1. Input delay – the browser is busy with other work when the user interacts.
  2. Processing time – your event handlers run.
  3. Presentation delay – the browser recalculates styles, lays out and paints the result.

Fixing INP means finding which part is slow.

Find the slow interactions

  • Field data – check the Core Web Vitals report or real-user monitoring to see which pages have poor INP.
  • Lab debugging – open Chrome DevTools, record a Performance profile, perform the interaction and look for long tasks around it.
  • Attribution – the web-vitals library reports which element and which phase caused the slow interaction.
javascript
import { onINP } from "web-vitals/attribution";

onINP(({ value, attribution }) => {
  console.log(value, attribution.interactionTarget, attribution.longestScript);
});

Fix 1: Break up long tasks

Any task over 50 ms blocks interactions. Split heavy work and yield to the browser between chunks.

javascript
const yieldToMain = () =>
  globalThis.scheduler?.yield ? scheduler.yield() : new Promise(r => setTimeout(r, 0));

async function processItems(items) {
  for (const item of items) {
    process(item);
    await yieldToMain(); // let the browser handle pending input
  }
}

Fix 2: Do less in event handlers

  • Update the UI first (show a pressed state or spinner), then do the heavy work.
  • Debounce input handlers for search boxes and filters.
  • Move expensive computation to a Web Worker.

Fix 3: Reduce rendering cost

  • Avoid re-rendering large component trees on every keystroke. Memoise, split state and use transitions for non-urgent updates in React.
  • Virtualise long lists.
  • Reduce DOM size; very large DOMs make style and layout slow.

Fix 4: Tame third-party scripts

Chat widgets, analytics and tag managers often run long tasks on the main thread. Load them later, remove what you do not need and check their impact in the profiler.

Fix 5: Avoid layout thrashing

Reading layout (offsetHeight, getBoundingClientRect) right after writing styles forces synchronous layout. Batch reads and writes.

Key takeaways

  • INP measures responsiveness; aim for 200 ms or less.
  • Find whether input delay, processing or presentation is the bottleneck.
  • Break up long tasks, keep handlers light and reduce rendering work.
  • Audit third-party scripts, which are common hidden culprits.