Interaction to Next Paint
Understand INP, the Core Web Vital that measures responsiveness by tracking the latency of user interactions from input to the next visual update.
Interaction to Next Paint (INP) measures the latency of every click, tap, and keyboard interaction throughout the entire page lifecycle, then reports a value representative of the overall responsiveness. A low INP means the page consistently responds quickly to user input. INP replaced First Input Delay (FID) as a Core Web Vital in March 2024.
Thresholds
| Rating | Value |
|---|---|
| Good | ≤ 200ms |
| Needs Improvement | 200ms – 500ms |
| Poor | > 500ms |
How INP Works
INP observes every discrete interaction (click, tap, keypress) during the page's lifetime. For each interaction, it records the total time from the moment the user triggers the input to when the browser paints the next frame reflecting the result.
The reported INP value is typically the worst interaction latency, unless there are many interactions — in which case it's approximately the 98th percentile. This means a few slow interactions will show up even if most interactions are fast.
INP measures the full round-trip from input to paint, not just how quickly the event handler runs. Even if your JavaScript executes in 10ms, the INP could be 300ms if the browser is busy with layout, paint, or compositing work afterward.
Understanding the Breakdown
Each interaction's latency is composed of three sequential phases:
Input Delay
The time from when the user interacts to when the event handler begins executing. This delay occurs when the main thread is busy with other work — typically a long-running JavaScript task that can't be interrupted.
Processing Duration
The time spent executing the event handler callbacks themselves. If multiple event listeners fire for the same interaction (e.g., pointerdown, pointerup, click), the processing duration covers all of them.
Presentation Delay
The time from when the last event handler completes to when the browser paints the next frame. This includes style calculations, layout, paint, and compositing work needed to display the visual result of the interaction.
INP = Input Delay + Processing Duration + Presentation DelayAttribution Data
When attribution is enabled, FastStats captures rich detail about the slowest interaction:
- Interaction Target — the CSS selector of the element the user interacted with
- Interaction Type —
pointer(click/tap) orkeyboard - Interaction Time — when the interaction occurred (ms from navigation start)
- Input Delay, Processing Duration, Presentation Delay — the three-phase breakdown
- Longest Script — the longest script that ran during the interaction, including which sub-part it overlapped with (input delay, processing, or presentation)
- Long Animation Frame Entries — the raw LoAF entries if available, for advanced debugging
Common Causes of Poor INP
Long Tasks on the Main Thread
JavaScript tasks exceeding 50ms are classified as "long tasks." If one is running when the user interacts, the event handler can't start until the task finishes, inflating the input delay.
Fix:
- Break long tasks into smaller chunks using
scheduler.yield()orrequestIdleCallback - Move heavy computation to a Web Worker
- Use
requestAnimationFramefor visual updates
Heavy Event Handlers
If your click or input handlers perform expensive synchronous work — like sorting a large list, computing a complex layout, or running deep DOM queries — the processing duration spikes.
Fix:
- Debounce or throttle expensive handlers
- Defer non-critical work with
queueMicrotask()orsetTimeout(fn, 0) - Avoid synchronous DOM measurements inside event handlers
Excessive DOM Size
Large DOM trees (over 1,000 elements) make style recalculation, layout, and paint more expensive, increasing the presentation delay.
Fix:
- Virtualize long lists (only render visible items)
- Remove unused DOM elements
- Simplify deeply nested structures
Forced Synchronous Layout (Layout Thrashing)
Reading layout properties (like offsetHeight) after writing to the DOM forces the browser to recalculate layout synchronously, blocking the main thread.
Fix: Batch DOM reads and writes. Read all layout properties first, then make changes:
const height = element.offsetHeight;
element.style.height = `${height + 10}px`;Third-Party Scripts
Analytics, ads, chat widgets, and other third-party scripts often run expensive code on the main thread that competes with your interaction handlers.
Fix:
- Load third-party scripts with
asyncordefer - Use
loading="lazy"for embeds - Evaluate whether each third-party script is necessary
INP vs. FID
| INP | FID | |
|---|---|---|
| Measures | All interactions throughout the page lifecycle | Only the first interaction |
| Includes | Input delay + processing + presentation delay | Only input delay |
| Reports | ~98th percentile of all interactions | Single measurement |
INP is a more comprehensive measure of responsiveness because it captures the full interaction lifecycle and considers all interactions, not just the first one.
Interpreting INP in FastStats
The metric detail page shows:
- p75 timeline — your INP score over time
- Distribution chart — spread of interaction latencies across rating buckets
- Three-phase breakdown — input delay, processing duration, and presentation delay visualized as a stacked bar
- Interaction targets — which elements users interact with and how slow each one is
- Breakdown by page — routes with the slowest interactions
- Device comparison — mobile devices typically have higher INP due to slower CPUs
First Contentful Paint
Understand FCP, the performance metric that measures how quickly the first piece of content renders on screen after navigation begins.
Largest Contentful Paint
Understand LCP, the Core Web Vital that measures loading performance by tracking when the largest visible element renders on screen.