Google’s official deprecation of First Input Delay (FID) and its replacement with Interaction to Next Paint (INP) represents the most demanding web responsiveness update in the history of Core Web Vitals. While FID merely measured the initial delay of the very first click on a page, INP tracks the responsiveness of every single click, tap, and keyboard interaction throughout a visitor’s entire browsing session, reporting the near-worst interaction latency.
Millions of websites that comfortably passed FID now fail Core Web Vitals due to sluggish JavaScript execution, heavy React hydration, and unoptimized DOM manipulations. Failing INP directly degrades your search rankings, increases bounce rates, and hurts e-commerce conversion rates. In this technical 2026 masterclass, you will learn the three phases of interaction latency, how to debug Long Animation Frames (LoAF), and the exact JavaScript architectural patterns to keep your INP under 200 milliseconds.
1. What is Interaction to Next Paint (INP) and Why FID Was Replaced
First Input Delay (FID) had a fatal flaw: it only measured the time from when a user first interacted with a page until the browser was able to begin processing the event. It completely ignored the time it took to actually execute the JavaScript callback and paint the updated visual frame. Furthermore, it only measured the first interaction, ignoring all subsequent clicks.
Interaction to Next Paint (INP) solves this by measuring the total end-to-end latency of all qualifying user interactions (clicks, screen taps, and keyboard strokes) throughout the entire page lifecycle. The 75th percentile of all interactions is selected as the page’s representative INP score.
2. The 3 Phases of User Interaction Latency
When a user taps an “Add to Cart” button or opens a navigation accordion, the total INP latency is the sum of three distinct phases:
Total INP = Input Delay + Processing Duration + Presentation Delay
| Latency Phase | What Is Happening in the Browser | Common Bottlenecks & Causes |
|---|---|---|
| 1. Input Delay | The time from user input until the browser’s main thread becomes idle enough to fire the registered event handler. | Long background JavaScript tasks (>50ms), heavy hydration loops, third-party analytics scripts running during page load. |
| 2. Processing Duration | The time spent actively executing the JavaScript code inside your event handler callbacks (e.g., onClick). |
Heavy computational calculations, synchronous API calls, complex state management recalculations in React/Vue. |
| 3. Presentation Delay | The time required for the browser to recalculate style trees, compute layout geometry, composite layers, and paint the next frame to screen. | Excessive DOM tree depth (>1,500 nodes), layout thrashing, expensive CSS blur/filter effects, synchronous reflows. |
3. Official Google INP Thresholds & Benchmarks
| Performance Tier | INP Value Range | Impact on Search Ranking & User Experience |
|---|---|---|
| Good (Passes Core Web Vitals) | ≤ 200 milliseconds | Full Core Web Vitals ranking signal boost; seamless, instantaneous UI response. |
| Needs Improvement | 201ms to 500ms | Borderline responsiveness; slight UI hesitation noticeable to users on budget mobile devices. |
| Poor (Fails Core Web Vitals) | > 500 milliseconds | Fails Google Page Experience criteria; high mobile rage-clicking and cart abandonment. |
4. How to Measure & Debug INP Using the Long Animation Frames API (LoAF)
To identify the exact JavaScript functions responsible for slow interactions, Chrome introduced the Long Animation Frames API (LoAF) in DevTools:
- Chrome DevTools Performance Panel: Open Chrome DevTools > Performance tab. Check “Screenshots” and “Web Vitals”. Set CPU throttling to 4x or 6x slowdown to simulate a real-world mobile device. Click Record, interact with your menus or buttons, and click Stop.
- Inspect the “Interactions” Track: DevTools highlights interactions in red if they exceed 200ms. Clicking the interaction reveals the exact breakdown between Input Delay, Processing Time, and Presentation Delay.
- Trace LoAF Script Execution: Expand the Main thread timeline directly under the interaction. LoAF pinpoints the exact script URL, function name, and line number that blocked the main thread.
5. Core Technical Fixes: Yielding with scheduler.yield()
When an event listener needs to perform multiple tasks, executing them synchronously in a single monolithic function blocks the main thread, delaying the next paint frame.
The solution is Yielding to the Main Thread: breaking heavy tasks into micro-chunks and yielding control back to the browser so it can render the visual response before completing background computation.
Modern Yielding Pattern with scheduler.yield():
// Modern asynchronous yielding utility
async function yieldToMain() {
if ('scheduler' in window && 'yield' in window.scheduler) {
return await window.scheduler.yield();
}
// Fallback for older browsers
return new Promise(resolve => setTimeout(resolve, 0));
}
// Optimized Click Event Handler
async function handleAddToCart(event) {
// 1. Immediately provide visual UI feedback (optimistic UI update)
updateButtonState('Loading...');
// 2. Yield control back to browser to PAINT the button state immediately!
await yieldToMain();
// 3. Perform expensive non-urgent operations in subsequent frame
performCartCalculations();
syncCartDataToBackend();
}
6. Eliminating Layout Thrashing & Forced Synchronous Reflow
Layout Thrashing occurs when JavaScript repeatedly reads layout geometric properties (like offsetWidth, clientHeight, or getBoundingClientRect()) and immediately writes style changes back to the DOM, forcing the browser to synchronously recalculate layout multiple times in a single loop:
// BAD: Causes forced synchronous reflow / High Presentation Delay
elements.forEach(el => {
const width = el.offsetWidth; // READ
el.style.width = (width + 10) + 'px'; // WRITE (forces re-layout!)
});
// GOOD: Batch all reads first, then batch all writes
const widths = elements.map(el => el.offsetWidth); // BATCHED READS
elements.forEach((el, i) => {
el.style.width = (widths[i] + 10) + 'px'; // BATCHED WRITES
});
7. Optimizing Modern Frameworks (Next.js, React 19 Hydration)
In server-side rendered (SSR) applications like Next.js, high Input Delay frequently occurs during Hydration (the window where HTML is painted on screen, but JavaScript is downloading and attaching event listeners):
- Server Components by Default: In Next.js 15/16 App Router, keep all static presentation components as React Server Components (RSC). Only mark leaf components that require interactivity (dropdown toggles, search inputs) with
"use client"to reduce client-side bundle size. - Transitions for Non-Urgent Updates: Use React’s
useTransition()orstartTransition()for expensive state updates (like filtering a 500-item table), allowing the browser to prioritize visual keystroke rendering over secondary list re-rendering. - Defer Non-Critical Third-Party Analytics: Load Google Tag Manager, Hotjar, and Facebook Pixel using
next/scriptwithstrategy="lazyOnload"so they never compete for CPU cycles during user interactions.
8. Frequently Asked Questions (FAQs)
Q: Why does my Lighthouse score show 100, but Search Console shows poor INP?
A: Lighthouse measures synthetic lab data under simulated conditions where no human actually clicks or interacts with the page. Google Search Console reports real-world Field Data (Chrome User Experience Report - CrUX) collected from millions of actual mobile users navigating your live website on varied hardware and network connections.
Q: Do scrolling and mouse hover count toward INP?
A: No. Scrolling and mouse hovering do not trigger INP measurements. INP strictly measures discrete discrete discrete input events: mouse clicks, touch-screen taps, and physical key presses (e.g., typing in an input field or pressing enter).
Q: How long does it take for INP improvements to reflect in Google Search Console?
A: Google Search Console uses a rolling 28-day aggregation window from the CrUX dataset. Once your code fixes are deployed to production, your GSC Core Web Vitals report will begin improving progressively over the subsequent 28 days.



