Interaction to Next Paint (INP) replaced First Input Delay (FID) as a Core Web Vital in March 2024. INP measures the latency of every user interaction (clicks, taps, key presses) throughout the entire page visit and reports the worst interaction (at the 98th percentile). This makes it significantly harder to pass than FID, which only measured the first interaction.
Google's INP Thresholds
| Rating | INP Value |
|---|---|
| Good | Under 200ms |
| Needs Improvement | 200ms - 500ms |
| Poor | Over 500ms |
Evaluated at the 75th percentile of page visits in CrUX field data. A page passes only if 75% of real user sessions have an INP under 200ms.
The Three Phases of an Interaction
Every interaction has three measurable phases. INP is the sum of all three:
- Input Delay -- time from user action to when the event handler starts running. Caused by other tasks blocking the main thread.
- Processing Time -- time spent executing the event handler(s) and any synchronous work triggered by the interaction.
- Presentation Delay -- time from when event handlers finish to when the browser renders the next frame (layout, paint, compositing).
To bring INP under 200ms, you need each phase contributing as little as possible. A common breakdown for a passing interaction: 30ms input delay + 100ms processing + 50ms presentation = 180ms.
Diagnosing INP Problems
Chrome DevTools
Open the Performance tab, enable "Interactions" in the timings lane, then interact with the page. Each interaction shows its total duration and breakdown across the three phases. Red-flagged interactions exceed 200ms.
Field Data
Check Search Console's Core Web Vitals report for INP status across your site. Use the web-vitals library with attribution for detailed field diagnostics:
import {onINP} from 'web-vitals/attribution';
onINP(metric => {
console.log('INP:', metric.value);
console.log('Element:', metric.attribution.interactionTarget);
console.log('Input Delay:', metric.attribution.inputDelay);
console.log('Processing:', metric.attribution.processingDuration);
console.log('Presentation:', metric.attribution.presentationDelay);
});
Reducing Input Delay
Input delay occurs when the main thread is busy with other work when the user interacts. The primary fix is eliminating long tasks (anything over 50ms):
- Break large JavaScript functions into smaller chunks using
scheduler.yield()orsetTimeout - Defer non-essential third-party scripts (analytics, ads, chat widgets)
- Use
requestIdleCallbackfor work that can wait
Reducing Processing Time
Optimize event handlers to do less synchronous work:
// Bad: synchronous DOM reads + writes in handler
button.addEventListener('click', () => {
const height = element.offsetHeight; // Forces layout
element.style.height = height + 100 + 'px'; // Triggers another layout
updateAllCards(); // Expensive synchronous loop
});
// Better: batch reads, minimize work, defer heavy operations
button.addEventListener('click', () => {
element.classList.add('expanded'); // CSS handles the transition
requestAnimationFrame(() => updateVisibleCards());
});
Avoid getComputedStyle, offsetHeight, getBoundingClientRect, and similar properties inside event handlers -- they force synchronous layout.
Reducing Presentation Delay
Presentation delay spikes when the browser must perform expensive layout, paint, or compositing after handler execution:
- Minimize DOM size (under 1,500 nodes recommended)
- Use CSS
contain: layouton independent UI sections - Avoid triggering layout thrashing (interleaved reads and writes)
- Prefer CSS animations over JavaScript-driven animations (CSS runs on the compositor thread)
Common INP Failures by Page Type
- E-commerce product pages: Carousel interactions, "Add to Cart" handlers with cart recalculation
- Content sites: Accordion/tab click handlers, lazy-load triggers on scroll
- Dashboards: Filter changes triggering large re-renders, table sorting
- Forms: Input validation on every keystroke, autocomplete dropdown rendering
Monitoring INP Over Time
Track INP in your analytics alongside page type and device category. Mobile devices consistently report worse INP than desktop due to slower processors. Set separate targets: under 200ms for desktop, under 300ms for mobile as an intermediate goal, tightening to 200ms as you optimize.