Table of Contents
- What Is Interaction to Next Paint
- INP vs FID: What Changed and Why It Matters
- The 2026 INP Thresholds and How Scoring Works
- How to Measure and Find Your Worst Interactions
- The Main Causes of Poor INP
- How to Fix INP: 8 Fixes That Actually Work
- Framework-Specific INP Guidance
- Frequently Asked Questions
What Is Interaction to Next Paint
INP measures the time from a user’s interaction to the next visual update of the page. It covers the full interaction lifecycle: the input delay while the main thread is busy, the event processing time of your handlers, and the presentation delay until the browser actually paints the result. A click that responds in 80 milliseconds feels instant; one that responds in 400 milliseconds feels broken.
Three interaction types are measured: clicks and taps with the mouse or finger, key presses on physical or on-screen keyboards, and – since the metric was refined – the full breadth of pointer and keyboard interactions users actually perform. Scrolling and hovering do not count, because they do not block the main thread the way discrete interactions do.
The paint requirement matters more than most teams realize: an interaction that fires a network request but updates nothing visible until the response lands will record a poor INP even though the JavaScript ran instantly. Show something immediately – a spinner, an optimistic UI state, a disabled button – and the same interaction scores beautifully.
INP vs FID: What Changed and Why It Matters
FID measured only the input delay of the first interaction – the gap between the tap and when the event handler could start running. It ignored everything after: how long your handler executed, whether the result painted, and how every subsequent interaction felt. In practice, a page could register an excellent FID while its menu clicks, filters, and form submissions took half a second each.
INP fixes all three blind spots. It considers every interaction on the page’s lifetime, and it measures through to the next paint rather than stopping when handler execution begins. Sites that optimized for FID by deferring work off the first tap often discover their real-world responsiveness was never as good as the lab suggested.
| Dimension | FID (retired) | INP (current) |
|---|---|---|
| Interactions measured | First interaction only | All interactions, worst-case scoring |
| What is measured | Input delay only | Input delay + processing + presentation delay |
| Paint requirement | No | Yes – next visual update required |
| Scrolling/hover | Excluded | Excluded |
| Good threshold | Under 100 ms | Under 200 ms |
| Field-data role | Core Web Vital until March 2024 | Core Web Vital and ranking signal since 2024 |
The 2026 INP Thresholds and How Scoring Works
The thresholds have been stable since INP replaced FID, and they align with how users perceive responsiveness:
- Good: 200 milliseconds or faster
- Needs improvement: between 200 and 500 milliseconds
- Poor: slower than 500 milliseconds
Two scoring rules trip up teams reading their dashboards. First, INP is reported at the page level as the approximate 98th percentile of observed interactions – the worst 1-in-50 experience defines your score, deliberately, because those users are the ones abandoning. Second, if a page has very few interactions (a content page with a single link click), the highest interaction duration is used instead of a percentile.
Crucially, INP is a field metric – real users, real devices, real networks – collected from Chrome users through the Chrome User Experience Report. Lab tools simulate interactions and are useful for debugging, but your official INP comes from the field. A perfect Lighthouse run means nothing if field data shows 600 millisecond interactions on mid-range Android phones, which is how the majority of the world actually browses. This field-versus-lab gap is a recurring theme across all Core Web Vitals, covered in the guide to Core Web Vitals optimization.
| INP Score | User Perception | Business Reality |
|---|---|---|
| Under 200 ms | Instant, native-app feel | Full engagement; metric passes |
| 200-500 ms | Slightly laggy but usable | Some abandonment on repeat interactions |
| Over 500 ms | Broken, unresponsive | Rage clicks, abandoned carts, ranking headwind |
How to Measure and Find Your Worst Interactions
Diagnosis has two layers: site-level status, then interaction-level forensics.
Layer 1: Establish where you stand
- PageSpeed Insights: enter any URL and read the Core Web Vitals Assessment. “INP” with a fail badge means the field 98th percentile misses the threshold. The “Diagnose” section shows lab values, but trust the field section for status.
- Search Console Core Web Vitals report: groups your URLs into good/needs-improvement/poor by template and device, telling you which page types drag the site – the fastest way to scope the project.
- CrUX dashboard: the Chrome User Experience Report history shows whether your INP trend is improving, which matters because Google evaluates the 28-day rolling window, not one-time snapshots.
Layer 2: Find the specific interactions that fail
Site-level scores do not tell you which button is slow. For that, field-debugging data is required:
- web-vitals JavaScript library: add the attribution build to your site and ship every interaction’s timing plus the attribution breakdown (input delay vs processing vs presentation delay) to your analytics. This converts INP from a mystery number into a per-element, per-page diagnosis.
- Real user monitoring tools: commercial RUM platforms surface your slowest interactions by selector and page template, with device and network segmentation – the segment that matters most is mid-tier mobile, where the majority of poor INP occurs.
- Chrome DevTools performance traces: once you know which interaction is slow, reproduce it locally with CPU throttling at 4x and network throttling to simulate the field. The trace shows the long tasks blocking the main thread during the interaction.
| Tool | Layer | What You Get |
|---|---|---|
| PageSpeed Insights | Field + lab status | Pass/fail, template-level issues, lab diagnostics |
| Search Console CWV report | Field, site-wide | Which URL groups fail and on which device |
| CrUX dashboard | Field, historical | 28-day trend per metric |
| web-vitals attribution build | Field, per-interaction | Element, timing breakdown, page for each slow interaction |
| RUM platform | Field, per-interaction | Selector-level ranking of worst interactions with segments |
| DevTools performance trace | Lab, debugging | Long tasks, handler time, paint timing for one interaction |
The Main Causes of Poor INP
Poor INP is almost always a main-thread congestion story. The usual suspects, in order of how often they are guilty:
- Long JavaScript tasks: any task over 50 milliseconds blocks the main thread. If one is running when the user taps, the input waits behind it. Bundle-heavy pages are chronically congested.
- Oversized event handlers: a click handler that sorts a 5,000-row table, recalculates layout, and fires three analytics calls all synchronously will blow the budget by itself.
- Forced synchronous layout: reading layout properties (offsetHeight, getBoundingClientRect) inside loops after writing to the DOM forces the browser to recalculate styles repeatedly – the classic layout thrashing death spiral.
- Third-party scripts: chat widgets, tag managers, A/B testers, and heatmaps run their own handlers on your main thread. Several popular tag managers measurably degrade interaction responsiveness on mobile.
- Hydration backlogs on SPA frameworks: until hydration completes, clicks queue with no listener or hit handlers not yet attached – users tap, nothing happens, INP records the delay.
How to Fix INP: 8 Fixes That Actually Work
1. Break up long tasks
Split any task over 50 milliseconds into smaller chunks, yielding to the main thread between them with scheduler.yield() (with setTimeout as the fallback). This single change – moving work from “one 300 ms block” to “six 40 ms blocks with yields” – lets pending inputs interleave with your work and routinely turns red INP green without removing any functionality.
2. Defer non-critical work out of handlers
Inside an event handler, do only what is needed for the visible response. Analytics beacons, prefetching, and non-visible DOM updates move to requestIdleCallback or fire-and-forget post-task scheduling. The user’s paint comes first; everything else queues behind it politely.
3. Show feedback immediately with optimistic UI
Paint something before doing the work: disable the button and show a spinner synchronously, render the added-to-cart state optimistically and reconcile when the server responds. Because INP measures through to the next paint, visible feedback is often the entire fix for network-dependent interactions.
4. Stop layout thrashing
Batch all DOM writes together, then batch all reads together – never alternate them inside a loop. Where the pattern is hard to unwind, read layout once before the loop and cache it. Profiling with DevTools’ performance panel makes the write-read-write oscillation visually obvious.
5. Shrink and split your JavaScript
Every kilobyte of parsed, executed bundle is main-thread congestion waiting to collide with an interaction. Code-split per route, tree-shake dead exports, and defer below-the-fold scripts. Pages with light bundles have main threads that are simply free when the user taps – the most reliable INP advantage of all. The measurement side of script weight lives in the guide to page speed optimization.
6. Audit third-party scripts ruthlessly
Inventory every third party on your worst-INP template, then test the page with each one blocked. Remove what nobody uses, delay what can load on interaction, and isolate what must stay (facade-loading chat and video embeds until first click). A single removed tag-manager misconfiguration has been known to fix a failing INP site-wide.
7. Fix hydration delays on SPAs
Reduce hydration cost with smaller initial component trees, and use framework features that avoid hydration entirely for static regions (server components, islands architecture). Interim mitigation: make interactive elements visibly disabled until hydrated so users never tap into a void – honest feedback beats silent failure for both users and INP.
8. Debounce high-frequency interactions
Search-as-you-type inputs, color pickers, and range sliders can trigger dozens of handlers per second. Debounce or throttle them so heavy work runs after the interaction burst settles, and render cheap intermediate states meanwhile. INP counts each interaction’s worst case; a slider that recalculates on every pixel is a score suicide.
| Fix | Effort | Typical INP Impact | Best For |
|---|---|---|---|
| Break up long tasks with yields | Low-Medium | Large – often 100-300 ms saved | Script-heavy pages |
| Defer non-critical handler work | Low | Medium-Large | Handlers with analytics/tracking inside |
| Optimistic UI / instant feedback | Low | Large for network interactions | Buttons, forms, cart actions |
| Fix layout thrashing | Medium | Large where present | Legacy DOM-heavy code |
| Reduce JavaScript bundle | Medium-High | Large, compounding | Everything |
| Third-party audit and facade-loading | Low-Medium | Medium-Large | Tag-manager-heavy templates |
| Hydration reduction | High | Large for SPAs | React/Vue application pages |
| Debounce high-frequency handlers | Low | Medium | Inputs, sliders, live search |
Framework-Specific INP Guidance
The fixes above are universal, but each ecosystem has its own INP personality.
- React: the default is synchronous re-render on state change – an expensive render on tap is a slow interaction. React 18+ concurrent features (startTransition, useDeferredValue) let you mark expensive updates as non-urgent so the click paints first. Memoized component trees and virtualized long lists cut render cost at the source.
- Vue: similar reactivity costs; use shallow references for large data, and chunk heavy watchers. Vue’s transition system can hide paint delays, but remember INP counts the paint of the response, not an overlay animation alone.
- Next.js and meta-frameworks: prefer server components to shrink client-side work, and audit the app router’s client boundary sprawl – every “use client” module ships main-thread cost to the browser.
- WordPress: the usual suspects are jQuery plugins bound to every click and page builders stacking handlers. Disable unused plugins on templates that fail INP, and audit builder widgets that attach global listeners; image and font hygiene also reduce main-thread contention during the interaction window.
Whatever the stack, the workflow is identical: measure in the field, reproduce the worst interaction under throttling, apply the relevant fix, verify the interaction improves in the lab, then watch the 28-day field trend confirm it. INP is one of three Core Web Vitals, and sites that fix responsiveness frequently find LCP and CLS regressions hiding underneath the same congestion – the full triage is in the guide to Core Web Vitals optimization. If your team’s roadmap has INP sitting in the “someday” column for two quarters, an outside audit from a Digimau engineer usually reprioritizes it – the fixes are smaller and the ranking stakes bigger than most teams assume.
Frequently Asked Questions
What is a good INP score in 2026?
200 milliseconds or faster is the good threshold. Between 200 and 500 milliseconds is needs improvement, and above 500 milliseconds is poor. The score is the 98th percentile of real-user interactions from Chrome field data over a 28-day window.
Why did INP replace First Input Delay?
FID only measured the delay before the first interaction’s handler could start, ignoring processing time, whether anything painted, and every interaction after the first. INP measures the full delay to the next visual update across all interactions, reflecting what users actually experience.
Does INP affect Google rankings?
Yes. INP has been one of the three Core Web Vitals used in Google’s page experience signals since March 2024. It is a ranking signal among hundreds, matters most on competitive queries, and passing all three vitals sets a floor rather than a ceiling.
How is INP calculated for pages with few interactions?
For pages with enough interactions, INP is approximately the 98th percentile of interaction durations. For pages with very few interactions, the worst single interaction’s duration is used instead.
How long does it take to see INP improvements in field data?
Field data uses a rolling 28-day window, so full credit for a fix takes up to a month to materialize, with early movement visible in days as new sessions replace old ones in the distribution.
Why is my INP bad on mobile but fine on desktop?
Mobile devices – especially mid-range Android – have slower CPUs and more main-thread contention. JavaScript that runs comfortably on desktop can block mobile interactions for hundreds of milliseconds. Always test under 4x CPU throttling to approximate field conditions.
Do third-party scripts affect INP?
Yes, significantly. Chat widgets, tag managers, A/B testing tools, and heatmaps run handlers on your main thread and compete with user interactions. Blocking each one in testing to measure its cost is a standard INP audit step.
What is the fastest way to improve a failing INP?
Find the worst interactions with web-vitals attribution data, then apply optimistic UI feedback so every interaction paints immediately, and break up long tasks with scheduler.yield(). These two changes fix most failing pages without deep refactoring.
Is INP measured in Lighthouse?
Lighthouse reports Total Blocking Time as a proxy in lab conditions because a single lab run cannot observe the 98th percentile of real interactions. Your official INP comes from Chrome field data via CrUX, so use Lighthouse for debugging and field data for status.
Does INP measure scrolling and hover effects?
No. INP only measures discrete interactions – taps, clicks, and key presses. Scrolling and hovering are excluded because they are handled differently by browsers and do not block the main thread the way discrete inputs do.
Related Articles
Keep reading with these guides: