SEO

INP Guide: How to Optimize Interaction to Next Paint

By SelestL • Published on
INP Guide: How to Optimize Interaction to Next Paint

When Google formally transitioned from First Input Delay (FID) to Interaction to Next Paint (INP) as an official Core Web Vital metric, the bar for web responsiveness was fundamentally raised. While FID measured only the initial delay of the very first user interaction on a page, INP assesses the responsiveness of every click, tap, and keypress across the entire lifecycle of a user session. If any interaction stalls the browser for more than 200 milliseconds, your page risks failing Google's Core Web Vitals threshold.

For engineering teams and technical SEOs, INP is often the most challenging metric to diagnose and resolve. Unlike Largest Contentful Paint (LCP), which primarily relates to server response times and asset delivery, INP is tightly coupled with client-side JavaScript execution, main-thread blocking tasks, DOM complexity, and rendering pipelines. Pages that pass automated lab tests with flying colors frequently fail in real-world field conditions on mobile hardware.

In this technical guide, we break down the three distinct phases of an interaction, examine official guidelines from web.dev INP metric documentation, review the W3C Event Timing API specification, and provide battle-tested code patterns from web.dev's Optimize INP technical guide to achieve green responsiveness scores.


The Anatomy of an Interaction: The 3 Phases of INP

The Anatomy of an Interaction: The 3 Phases of INP

INP does not simply measure how long a JavaScript callback takes to execute. It measures the complete round-trip time from the moment a physical user interaction begins until the browser finishes painting the resulting visual update to the screen. Every interaction is composed of three sequential phases:

Phase What Occurs Typical Bottleneck
1. Input Delay Time between user action (click/keypress) and when the browser can begin running event handlers. Long Tasks running on the main thread from background scripts, tag managers, or hydration.
2. Processing Duration Total execution time of all synchronous JavaScript event callbacks tied to the interaction. Heavy business logic, complex data transformations, synchronous DOM queries, or heavy state updates.
3. Presentation Delay Time required for the browser to recalculate styles, recalculate layout reflows, and composite pixels on the GPU. Overly large DOM trees, complex CSS selectors, layout thrashing, and rendering heavy animations.

Google Core Web Vitals Thresholds for INP

  • Good (Passing): 200 milliseconds or less.
  • Needs Improvement: Between 200 milliseconds and 500 milliseconds.
  • Poor (Failing): Greater than 500 milliseconds.

Google evaluates INP at the 75th percentile of page visits recorded across real Chrome users over a rolling 28-day collection window, as aggregated in the Chrome User Experience Report (CrUX).


Field Data (CrUX) vs Lab Data (Lighthouse)

One of the most frequent points of confusion among engineering teams is why their Google Lighthouse score reports 95+ while Google Search Console flags failing INP URLs. Lighthouse is a synthetic lab tool that runs on high-end virtual hardware with simulated network throttling. Crucially, synthetic tools do not click navigation toggles, scroll through complex faceted menus, type in search filters, or interact with modal accordions the way real humans do.

INP is fundamentally a field metric. If a user on a budget Android smartphone with a throttled mobile processor clicks a mobile hamburger menu while a heavy marketing tag runs in the background, their device will experience a 450ms main-thread freeze. That interaction is recorded in CrUX and impacts your search performance.


Core Engineering Fixes to Optimize INP

Optimizing INP requires systematically reducing main-thread congestion across all three interaction phases.

1. Yielding to the Main Thread

When an event listener must execute multiple operations, running them in a single monolithic synchronous block blocks the main thread, causing presentation delay. By breaking long tasks into smaller chunks and yielding control back to the browser between operations, the rendering engine can paint the next visual frame immediately.

The modern standard for cooperative scheduling is scheduler.yield(), with fallbacks utilizing setTimeout or MDN requestIdleCallback:

// Cooperative Main-Thread Yielding Helper
function yieldToMain() {
  if ('scheduler' in window && 'yield' in window.scheduler) {
    return window.scheduler.yield();
  }
  return new Promise((resolve) => {
    setTimeout(resolve, 0);
  });
}

// Example: Processing a large list without blocking the frame
async function handleFilterSubmit(items) {
  // 1. Immediately provide visual feedback to user
  showLoadingSpinner();
  
  // Yield to allow the browser to paint the spinner
  await yieldToMain();

  // 2. Perform chunked processing
  for (let i = 0; i < items.length; i += 50) {
    processBatch(items.slice(i, i + 50));
    // Yield every batch so user clicks or scrolls are not frozen
    await yieldToMain();
  }

  // 3. Render final results
  renderResults();
}

2. Eliminating Layout Thrashing (Forced Synchronous Layouts)

Layout thrashing occurs when JavaScript repeatedly interleaves reading geometric properties (such as offsetHeight, clientWidth, or getBoundingClientRect()) with writing styles to the DOM. Each read forces the browser to synchronously recalculate layout calculations before continuing script execution.

  • Bad Practice: Reading an element's width, immediately changing its width in CSS, then reading another element's height in a loop.
  • Good Practice: Batch all read operations together, then batch all write operations, or use CSS transforms (transform, opacity) that run on the GPU compositor thread without triggering layout reflows.

3. Optimistic UI Updates

Never wait for asynchronous network requests or heavy database computations to complete before acknowledging user input. When a user clicks an "Add to Cart" or "Expand Accordion" button, update the component visual state immediately (e.g., toggling the icon or displaying a loading state) within 50ms, and perform the data fetching asynchronously in the background.


Measuring INP in Production with the web-vitals Library

To detect exactly which components and DOM elements cause slow interactions on your production site, instrument real-user monitoring (RUM) using the official Google web-vitals library:

<!-- Real User Monitoring for INP Attribution -->
<script type="module">
  import { onINP } from 'https://unpkg.com/web-vitals@4?module';

  onINP((metric) => {
    // Log the full attribution object for slow interactions
    if (metric.value > 200) {
      console.warn('Slow INP Detected:', {
        value: metric.value,
        rating: metric.rating,
        interactionTarget: metric.attribution.interactionTarget,
        interactionType: metric.attribution.interactionType,
        inputDelay: metric.attribution.inputDelay,
        processingDuration: metric.attribution.processingDuration,
        presentationDelay: metric.attribution.presentationDelay,
      });

      // Transmit beacon to your analytics backend
      navigator.sendBeacon('/api/telemetry/vitals', JSON.stringify({
        metric: 'INP',
        duration: metric.value,
        target: metric.attribution.interactionTarget,
        page: window.location.pathname
      }));
    }
  });
</script>

This attribution data pinpoints the exact HTML element (such as button#mobile-nav-toggle) responsible for your 75th-percentile INP spikes.


Strategic Checklist for Green INP Performance

  • Audit Third-Party Scripts: Defer or remove non-essential tag managers, session replay trackers, and chat widgets that hijack the main thread during user interactions.
  • Implement Virtualization for Large Lists: Avoid rendering thousands of DOM nodes in dropdowns or catalogs; render only visible items using windowing techniques.
  • Debounce Input Handlers: Apply debouncing or throttling to search input fields, auto-complete forms, and resize listeners to prevent rapid callback firing.
  • Prioritize CSS Compositing: Animate exclusively via transform and opacity to bypass style recalculation and layout phases.
  • Review Technical Architecture: Pair responsive client interfaces with sound technical foundations. Review our Technical SEO Audit Framework, optimize your asset rendering via our Image Optimization Guide, and ensure proper crawl routing with our Faceted Navigation Guide.

Need dedicated performance engineering to optimize Core Web Vitals, refactor complex frontend architectures, or streamline JavaScript execution? Learn more about our custom engineering services or contact our technical team via our consultation portal.

Related Articles