Interaction to Next Paint measures the thing that makes a site feel alive: when you tap, type, or click, how long until the screen actually updates? It watches every interaction for the whole visit and reports the worst. Good is ≤ 200 ms; cross ~500 ms and the page feels broken.
See it for yourself
Feel a slow interaction
Turn up the background work — simulating JavaScript hogging the main thread — then tap the button. The “Done” state only appears after the interaction completes, so you literally feel the lag. Then flip the optimize switch and watch INP fall back into the green:
InteractiveINP live simulator
60%
Taps: 0
Crank up background work, then tap — feel the delay before “Done” appears.
Background work delays when the browser can even start your handler (input delay). Optimizing yields the thread and shrinks the work.
That was a simulation — this one is not. The search box below filters 30,000 products with a deliberately expensive scorer, and every keystroke's input→paint delay is measured on your machine with performance.now(). Mash the keyboard in each mode and watch the chips:
InteractiveSearch 30,000 products — your real input latency
The full 30,000-item filter (with a deliberately expensive fuzzy score) runs inside the input handler. Type fast and feel the keys stick.
Worst keystroke → paint
—
Matches
0
Results ready in
—
30,000 products loaded. Start typing.
The latency chips are real: performance.now() at the input event, read again after the next frame paints. Green is under 100 ms — the INP “good” threshold. Mash the keyboard in the first mode, then switch and mash again.
Blocking filters inside the handler; debouncing delays the work; chunking slices it with yields so the thread stays free to paint. Green chips are under the 100 ms INP threshold.
What's an 'interaction'?
An interaction is a group of events
From the user's view, they “clicked a button.” Under the hood, that fires a group of events — and INP measures the whole group plus the paint after it. INP only counts clicks, taps, and keystrokes; hover and scroll don't count:
InteractiveOne interaction → several events
one interaction →pointerdownpointerupclick
INP measures the whole group — every handler that fires for the interaction, plus the paint that follows. Each handler is a chance to do too much work. (Note: hover and scroll don't count toward INP.)
Each event can run its own handler. The slowest path through them all is what INP captures.
The anatomy
The three phases
Every interaction breaks into three phases — and the live demo above maps directly onto them:
Input delay — from your tap until the browser is free to run the handler. Big when the main thread is busy.
Processing time — running all the event handlers for the interaction.
Presentation delay — recalculating layout and painting the next frame.
Key idea
Because JavaScript is single-threaded, a long task already running means your tap just waits. That wait is input delay — the most common reason interactions feel sluggish.
Why it replaced FID
INP vs the old FID
FID (old)
INP (now)
What it measures
Input delay of the first interaction only
Full duration of (nearly) every interaction
Covers
Just the first tap
The whole visit
Catches late slowdowns
No
Yes (e.g. memory leaks)
Includes processing + paint
No, delay only
Yes
FID could call a site “responsive” off one fast first tap, even if it bogged down later. INP watches the whole session, so it reflects how the app actually feels over time.
What to actually do
Optimizing each phase
Input delay — yield the main thread
The thread is often busy with script evaluation (downloading, parsing, compiling, running JS) right when the user first interacts. Ship less JS, defer non-critical work, and break long tasks so the thread is free to respond.
Processing time — do less, and break it up
In the handler, do only the critical work (show the visual feedback the user expects) and push the rest — analytics, syncing, spell-check — into a later task so the paint isn't blocked:
render first, defer the rest
input.addEventListener("input",(e)=>{updateTextbox(e);// critical: user must SEE their text nowsetTimeout(()=>{// hand the rest to a later taskupdateWordCount();runSpellCheck();syncToServer();},0);});
Presentation delay — paint less
A huge DOM makes every frame expensive. Keep the DOM lean, render only what's above the fold, and use content-visibility: auto to let the browser skip off-screen work.
Q1Multiple choice
A dashboard feels janky while scrolling and hovering charts, yet its INP looks great. Why might INP miss this?
Q2Multiple choice
Clicking 'Filter' highlights the button instantly, but results take 400ms to appear and the page is frozen during it. Which INP phase dominates, and the fix?
Q3Multiple choice
Your INP is poor, but only the 'Export' button is slow — every other interaction is snappy. A teammate says 'it's one button, ignore it.' Why can't you?
Q4Sort each scenario
Each symptom points to one INP phase. Sort them.
A long task is still running, so your tap's handler can't even start
A third-party script monopolizes the thread the moment you click
The handler runs an expensive 300ms calculation before responding
The handler is quick, but the resulting update repaints a massive DOM
Key takeaways
→INP measures responsiveness across the whole visit. Good ≤ 200 ms, poor > 500 ms.
→It counts clicks, taps, keystrokes — not hover or scroll — and measures the whole event group + paint.