Skip to main content

    INP

    INP measures interaction latency (user input to visual update). It replaces FID and reflects main-thread JS long tasks.

    Definition

    INP (Interaction to Next Paint) is a Core Web Vitals interaction metric measuring the delay from user interaction to the next visual update. It's influenced by long tasks, heavy JS, third-party scripts, and main-thread blocking.

    Why it matters

    • Directly impacts responsiveness and user perception of 'laggy' sites
    • Officially replaced FID in March 2024 as the Core Web Vitals interaction metric
    • Poor INP hurts conversion rates and user satisfaction
    • Reflects real interaction quality, not just the first click
    • Third-party scripts (analytics, ads) are often the culprit of INP issues
    • Too much JS blocks the main thread, causing unresponsive clicks
    • Good INP makes users feel the site is 'smooth'

    How to implement

    • Split JS, defer non-critical scripts, use async/defer
    • Identify and eliminate long tasks (>50ms): analyze with DevTools Performance
    • Use Web Workers to move heavy computation off the main thread
    • Reduce third-party script burden: defer loading, use facades
    • Optimize event handlers: debounce/throttle, avoid complex DOM operations
    • Use requestAnimationFrame for visual updates
    • Monitor INP: use web-vitals library or RUM for ongoing tracking

    Examples

    html
    import { onINP } from 'web-vitals';
    
    onINP((metric) => {
      console.log('INP:', metric.value, 'ms');
      console.log('Rating:', metric.rating); // 'good' | 'needs-improvement' | 'poor'
      
      // Report to analytics
      analytics.track('INP', {
        value: metric.value,
        rating: metric.rating
      });
    });
    html
    // Long task splitting (experimental API)
    async function processItems(items) {
      for (const item of items) {
        processItem(item);
        
        // Yield to main thread after each item
        if ('scheduler' in window && 'yield' in scheduler) {
          await scheduler.yield();
        } else {
          await new Promise(r => setTimeout(r, 0));
        }
      }
    }

    Related

    FAQ

    Common questions about this term.

    Back to glossary