OmniWire ToolsHub
Web Vitals 9 min read 2026-03-25

Understanding INP (Interaction to Next Paint) in 2026

A deep technical breakdown of Google's Core Web Vitals metric INP, why it replaced FID, and how to identify and eradicate long tasks in JavaScript.

D
Devin Chen
Frontend Runtime Specialist • OmniWire Research

Why Interaction to Next Paint Replaced First Input Delay

In March 2024, Google officially transitioned from First Input Delay (FID) to Interaction to Next Paint (INP) as an official Core Web Vitals responsiveness metric. While FID merely measured the latency of the user's first interaction, INP measures the latency of all qualifying user interactions throughout the entire lifespan of the page visit.

INP records the worst (or near-worst 98th percentile) interaction latency, tracking three distinct sub-phases:

  1. Input Delay: Time spent waiting for main thread background tasks to clear before the event callback can start.
  2. Processing Time: The duration required to execute your JavaScript event listeners (click, keydown, pointerdown).
  3. Presentation Delay: The time the browser engine needs to recalculate layout, restyle the DOM, composit layers, and present the newly rendered frame to the physical display.

Understanding the 2026 INP Thresholds

  • Good: Less than or equal to 200 ms. (Ensures UI feels instant and buttery smooth).
  • Needs Improvement: Between 200 ms and 500 ms.
  • Poor: Greater than 500 ms. (Results in search ranking penalties and visible user frustration).

Eradicating Long Tasks with scheduler.yield()

The number one cause of high INP is long JavaScript tasks (tasks exceeding 50ms) blocking the main browser thread. When a user clicks a button while a heavy calculation or JSON formatting is executing, the click event cannot be processed until the task completes.

Modern web browsers offer the scheduler.yield() API (with a fallback to setTimeout()) to yield control back to the rendering engine:

// Modern yield mechanism to keep main thread responsive
async function yieldToMain() {
  if ('scheduler' in window && 'yield' in window.scheduler) {
    return await window.scheduler.yield();
  }
  return new Promise((resolve) => setTimeout(resolve, 0));
}

// Process large datasets without freezing UI
async function processLargeBatch(items) {
  for (let i = 0; i < items.length; i++) {
    doIntensiveWork(items[i]);
    // Yield every 50 items to paint UI updates
    if (i % 50 === 0) {
      await yieldToMain();
    }
  }
}

Visualizing Layout Thrashing

Another common culprit is interleaved DOM read and write operations. Reading layout metrics (like offsetHeight, scrollTop, getBoundingClientRect()) immediately after modifying styles forces synchronous layout recalculation. Always batch style reads first, then execute writes together.

⚡ Interactive Diagnostic: Simulate INP, LCP, and CLS scores and calculate overall page health in our Site Speed & Core Web Vitals Hub.
← Back to Tutorial Archive
ADVERTISEMENT