Interaction to Next Paint (INP)
👆 Interaction to Next Paint (INP)
The Three Sub-Parts of an Interaction
INP measures the full round trip of an interaction, in three stages — a parallel structure to Chapter 2's four-part LCP breakdown:
| Stage | What It Covers |
|---|---|
| Input delay | Time before the event handler even starts running |
| Processing time | How long the handler itself takes to run |
| Presentation delay | Time until the next frame is actually painted, showing the result |
INP reports a high-percentile value (around the 98th percentile, excluding a small number of outliers) across every interaction in the page's session — reinforcing Chapter 1's FID-vs-INP point with the actual measurement behind it: one bad first click no longer defines the score, but neither does a good one.
Why a High Percentile, Not an Average
A single terrible interaction sticks in a user's memory even if most interactions felt fine — averaging would wash that out. A high percentile deliberately keeps the worst realistic experience visible.
Every Interaction, Not Just the First
Unlike FID, a page that's fast on click one but sluggish on click fifteen will show that in its INP score — nothing before this metric tracked that at all.
🧵 Why the Main Thread Is the Bottleneck
JavaScript execution, style recalculation, layout, and paint all compete for the same single main thread. If a long JS task is already running when a user clicks, the click's event handler can't even start until that task finishes — directly inflating input delay.
Long Tasks
Any task occupying the main thread for more than 50ms is considered a "long task" — the most common root cause of poor INP, detectable via the Long Tasks API.
Common Causes
Heavy synchronous JS, large third-party scripts (analytics, ads, chat widgets) running arbitrary code on the same thread, framework re-renders touching too much of the DOM, and expensive work done directly inline inside event handlers.
A Direct Link to Chapter 7
Expensive DOM queries or reflows running on every scroll event is exactly the debounce/throttle problem from JS Advanced, applied here at the whole-page level — Chapter 7 covers this in depth.
Breaking Up Long Tasks
The fix is yielding to the main thread periodically during expensive work, so pending input and paint can be processed between chunks:
Blocking vs Yielding
setTimeout(fn, 0) is the classic yielding technique; requestIdleCallback suits lower-priority background work, and the newer scheduler.yield() offers a cleaner, purpose-built API for the same idea.
Felt Experience
Blocking
A click during the loop sits queued for hundreds of milliseconds — visible, frustrating lag.
Yielding
The same total work completes, but the browser can slip the click's handler in between chunks — it feels instant.
💻 Coding Challenges
Challenge 1: Identify the Long Task
A button click triggers a function that loops over 10,000 array items doing synchronous work, taking 300ms total, before updating the DOM. Explain which INP sub-part this most directly inflates, and why.
Goal: Practice mapping a concrete code pattern onto the three-part INP breakdown.
Challenge 2: Chunk a Long-Running Function
Rewrite a function that synchronously processes 5,000 items in one pass into a chunked version using the pattern from this chapter, processing 100 items per chunk.
Goal: Practice applying the yielding pattern to a different chunk size and workload.
Challenge 3: Explain Why Percentile Beats Average Here
A page has 100 interactions in a session: 95 take 50ms and 5 take 800ms. Explain what the average would suggest about the page's responsiveness versus what a high-percentile INP score would show, and why the high-percentile view is more useful.
Goal: Practice reasoning about why INP's percentile design choice matters in a concrete case.
Third-party scripts — analytics, ad networks, chat widgets, tag managers — run on the exact same main thread as first-party code, and are extremely common, often dominant, contributors to poor INP. It's easy to profile and optimize a team's own event handlers while a marketing team's tag manager script quietly runs a 400ms long task on every page. Auditing INP means auditing every script actually running on the page, not just the ones a given team wrote — third-party scripts are often added by other teams without engineering ever seeing their performance cost.
🎯 What's Next
With all three Core Web Vitals covered in depth, the next chapter turns to a concrete, high-impact fix for several of them at once: Image Optimization — modern formats, responsive images, and lazy loading.