HTML Tutorial 0/139 lessons ~6 min read Lesson 99

    Interaction to Next Paint (INP)

    interaction to next paint (inp) interaction to next paint captures full responsiveness from input to visual upda interaction to next

    Course progress0%
    Focus
    18 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    Interaction to Next Paint (INP) measures responsiveness: latency from user interaction (click, tap, key) until the browser paints the next frame showing visual feedback. INP replaced First Input Delay (FID) in Core Web Vitals March 2024 because FID only captured first input and ignored slow event handlers.

    The Chrome team documents INP on web.dev — it aggregates worst interactions (approximately 98th percentile) and exposes main-thread congestion that HTML script loading strategies directly influence.

    Business problem

    Business pressure: SaaS dashboard with 800KB React bundle scored Good FID (0ms — no blocking before first click) but Poor INP (480ms) — every filter click waited on main-thread re-render. Support tickets: "UI frozen." CrUX INP failed after Google switched metrics.

    • Conversion: Slow add-to-cart button response loses mobile shoppers — INP captures sustained pain FID missed.
    • Compliance: Keyboard users activating controls need prompt focus feedback — INP measures that delay.
    • SEO: INP in CrUX affects page experience signals alongside LCP and CLS.

    Why this feature exists

    Platform motivation: FID only measured delay before first event handler ran — not handler duration or subsequent interactions. INP reflects full interaction-to-paint latency users feel on every click.

    • History: Event Timing API matured; INP built on processing duration + presentation delay.
    • Alternative rejected: Total Blocking Time (lab-only) does not represent real interaction patterns.
    • Modern role: Long Animation Frames API and scheduler APIs help diagnose INP in Chrome.

    Browser internals

    Inside the engine: Input dispatched on main thread (unless offloaded). Event handlers run; style/layout/paint may follow; frame presented. INP = interactionTime to nextPaintTime for slow interactions. Long tasks (>50ms) during interaction inflate INP. Compositor-only updates can reduce presentation delay.

    • Event Timing: duration, processingStart, processingEnd, interactionId.
    • Presentation delay: Time from handler end to frame with visual update.
    • INP aggregation: Highest interaction latency observed (with outlier handling per spec).
    • Passive listeners: Allow scroll to proceed — improve perceived responsiveness.
    text
    Click event
    → (input delay if main thread busy)
    → event handlers (JS)
    → style/layout/paint (if needed)
    → composite frame
    → INP = time to that paint

    Rendering workflow

    Rendering path: Handler mutating DOM triggers style/layout/paint before next frame — extends INP. Deferring DOM work to rAF or using CSS class toggles on compositor-friendly properties reduces presentation delay.

    • Critical path: Parser-blocking JS increases baseline main-thread busy-ness before any interaction.
    • Layout: Synchronous layout in click handler directly blocks paint.
    • Composite: Feedback via transform/opacity can paint faster than layout-heavy updates.

    Feature deep dive

    INP optimization per web.dev: minimize long tasks; break up JS; use web workers for heavy compute; reduce DOM size; optimize event handlers; show immediate visual feedback (optimistic UI). Good INP ≤ 200ms at p75.

    • Yield to main: scheduler.yield(), setTimeout(0), requestIdleCallback patterns.
    • Debouncing: Coalesce rapid input — but first interaction must still feel instant.
    • SSR HTML: Interactive before hydration — progressive enhancement lowers INP risk.
    • Third parties: Analytics hooks on every click add handler cost.
    html
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>INP Demo</title>
    <style>
    button { padding: 1rem 2rem; font-size: 1rem; }
    button:active { transform: scale(0.98); }
    #out { margin-top: 1rem; font-family: monospace; }
    </style>
    </head>
    <body>
    <h1>INP: Fast vs Slow Handler</h1>
    <button id="fast">Fast feedback</button>
    <button id="slow">Slow handler (blocks)</button>
    <div id="out"></div>
    <script>
    const out = document.getElementById('out');
    document.getElementById('fast').onclick = () => { out.textContent = 'Updated ' + Date.now(); };
    document.getElementById('slow').onclick = () => {
    const start = performance.now();
    while (performance.now() - start < 200) {} // simulate long task
    out.textContent = 'Slow update ' + Date.now();
    };
    </script>
    </body>
    </html>

    Accessibility analysis

    A11y architecture: INP includes keyboard activation — Enter/Space on button must produce timely focus/state change. Delayed aria-expanded update feels broken to screen reader users even if visual spinner appears.

    • Screen readers: Announce state after DOM update — slow INP delays announcement sync.
    • Keyboard: :focus-visible styles should paint in same frame as activation when possible.
    • WCAG: 2.5.2 Pointer Cancellation — related UX; INP measures outcome timing.

    SEO impact

    SEO architecture: INP appears in Search Console CWV report. Poor INP correlates with lower engagement — indirect ranking factor. Googlebot does not measure INP, but users and CrUX do.

    • Crawl: No direct INP impact on crawl.
    • Rich results: Interactive widgets with Poor INP hurt UX signals on landing pages with schema.
    • Core Web Vitals: INP is second CWV pillar for interactivity post-2024.

    Security considerations

    Security boundary: Cryptomining or fingerprinting scripts create long tasks — INP degradation as side effect. CSP reduces unauthorized script INP impact.

    • XSS: Malicious handlers on capture phase slow every interaction.
    • CSP: Restrict script sources — fewer third-party INP regressions.
    • Clickjacking: Separate from INP — but slow response helps users detect hijacked UI.

    Performance impact

    Performance: INP is the interactivity Core Web Vital. Chrome DevTools Performance → Interactions track; web.dev INP guide maps optimizations. RUM must capture Event Timing with correct attribution.

    • LCP: Heavy JS before LCP often same bundle hurting INP later.
    • INP: Primary metric for handler and main-thread optimization.
    • CLS: Independent — but shared root cause in DOM-heavy updates.

    Real production example

    Production pattern: Google Search improved INP by yielding during long JavaScript tasks using scheduler.yield() — Chrome team blog pattern. E-commerce sites defer non-critical hydration with islands architecture — HTML interactive shell first.

    • Pattern: Split bundle; idle hydration; optimistic button state via CSS :active immediately.
    • Monitoring: web-vitals.js report INP + attribution to GA4.
    • Fix: Moved filter sort from sync 120ms handler to worker — INP p75 280ms → 160ms.

    Enterprise usage

    Enterprise: Data grids instrument interaction traces in staging — click cell → edit must meet INP budget <200ms on reference laptop and Moto G Power.

    • Design system: Buttons show instant :active feedback while async work runs.
    • CMS: Limit embed scripts attaching global click listeners.
    • CI gates: Puppeteer CDP Performance interactions on checkout flow.

    Common production failures

    What breaks in prod: document.addEventListener('click') analytics scanning entire DOM each click — INP Poor on all pages. FID was Good because first click happened before analytics loaded.

    • Incident: React 18 transition not used — full tree re-render on each keystroke in search.
    • SEO regression: CrUX INP Poor after chatbot addition — long tasks on open.
    • Perf regression: Synchronous localStorage write in every button handler.

    Architecture review questions

    • What is CrUX INP p75 for our origin — Good, NI, or Poor?
    • Which interactions have worst Event Timing duration in RUM?
    • Are we shipping less JS in initial HTML than last year?
    • Do handlers yield for long loops (>50ms)?
    • Is visual feedback immediate (CSS) while async work completes?
    • Did INP replace FID in our dashboards and alerting?

    Hands-on project

    Project: Use DevTools Performance → Interactions to record slow button click. Identify long task between input and paint. Refactor to yield or reduce work; remeasure INP in lab interaction test.

    • Deliverable: Before/after interaction trace + handler code diff.
    • Verify: web.dev optimize INP; Event Timing in Performance API.
    • Stretch: Integrate web-vitals onClick attribution in staging RUM.

    Interview questions

    How is INP different from FID?(Intermediate)

    FID measured first-input delay only — time from input until handler starts, excluding handler time. INP captures full latency from interaction to next paint for all interactions (worst/slow interactions aggregated). INP ≤200ms Good vs FID ≤100ms.

    Follow-up: Why did Google replace FID?

    What causes high INP on a React SPA?(Advanced)

    Large hydration cost, synchronous re-renders on interaction, heavy event handlers, layout thrashing in handlers, third-party scripts, main-thread long tasks. Fix: code split, transitions, workers, defer hydration, compositor-friendly feedback.

    Follow-up: Role of SSR HTML for INP?

    How does HTML script loading affect INP?(Advanced)

    Parser-blocking and large sync JS in head keeps main thread busy before and during interactions. defer/module reduces blocking; less JS shipped via HTML means faster handler execution and shorter presentation delay.

    Follow-up: Does compositor help INP?

    Try it yourself

    Edit the HTML, CSS, or JS panels — the preview updates as you type.

    Try it yourself

    Preview

    Summary

    Interaction to Next Paint captures full responsiveness from input to visual update. The Chrome team defines INP on web.dev; HTML script strategy and main-thread discipline determine CrUX INP p75 in the field.

    Ready to mark this lesson complete?Track your journey across the entire course.