Interaction to Next Paint (INP)

Master the art of optimizing page responsiveness to improve user interactions, pass Core Web Vitals, and provide a smooth, responsive experience.

What is Interaction to Next Paint?

Interaction to Next Paint (INP) measures the time from when a user interacts with your page (clicks, taps, key presses) to when the browser can respond to that interaction by showing the next frame. It replaced First Input Delay (FID) in 2025 as it provides a more comprehensive view of page responsiveness.

Unlike FID, which only measured the delay for the first input, INP considers the responsiveness of the entire page throughout the user's session, offering a broader and more accurate reflection of the user experience.

INP vs FID: Key Differences

FID (Old)

  • • Only first interaction
  • • Input delay only
  • • Limited scope
  • • Less representative

INP (New)

  • • All interactions
  • • Full interaction time
  • • Session-wide view
  • • More accurate
INP Performance Chart

INP Scoring Criteria

Understand what constitutes good, needs improvement, and poor INP scores

Good

≤ 200ms

Your page responds quickly to user interactions

⚠️

Needs Improvement

200ms - 500ms

Some interactions may feel sluggish

Poor

> 500ms

Users experience significant delays

How INP is Calculated

INP Components

  • Input Delay: Time before event handlers run
  • Processing Time: Event handler execution time
  • Presentation Delay: Time to render next frame

What Affects INP

  • Long JavaScript tasks
  • Heavy DOM manipulation
  • Large style calculations
  • Main thread blocking

Common INP Issues

Identify and fix the most common causes of poor INP scores

⏳ Long JavaScript Tasks

JavaScript tasks that take more than 50ms block the main thread and prevent the browser from responding to user interactions quickly.

Solutions:

  • • Break up long tasks into smaller chunks
  • • Use Web Workers for heavy computation
  • • Implement yielding with scheduler.yield()
  • • Defer non-critical JavaScript

🔄 Excessive DOM Updates

Frequent DOM manipulations, especially in loops, can cause layout thrashing and block the main thread, leading to poor responsiveness.

Solutions:

  • • Batch DOM updates
  • • Use DocumentFragment for multiple inserts
  • • Minimize layout thrashing
  • • Use CSS transforms instead of layout changes

🎨 Expensive Style Calculations

Complex CSS selectors, large DOM trees, and frequent style changes can cause expensive style and layout calculations that block the main thread.

Solutions:

  • • Simplify CSS selectors
  • • Reduce DOM complexity
  • • Use CSS containment
  • • Avoid synchronous layout reads

📊 Heavy Event Handlers

Event handlers that perform heavy computations or DOM manipulations can block the main thread and prevent quick response to user interactions.

Solutions:

  • • Debounce high-frequency events
  • • Optimize event handler logic
  • • Use passive event listeners
  • • Offload work to Web Workers

INP Optimization Techniques

Proven strategies to improve page responsiveness

Break Up Long Tasks

Long JavaScript tasks (>50ms) block the main thread and prevent the browser from responding to user interactions. Breaking these tasks into smaller chunks improves responsiveness.

Benefits:

  • Better main thread availability
  • Improved user responsiveness
  • Smoother animations
  • Better INP scores

Code Example:

// ❌ Bad: Long synchronous task function processLargeDataset(data) { const results = []; for (let i = 0; i < data.length; i++) { results.push(expensiveOperation(data[i])); } return results; } // ✅ Good: Break into chunks with yielding async function processLargeDataset(data) { const results = []; for (let i = 0; i < data.length; i++) { results.push(expensiveOperation(data[i])); // Yield to browser every 10 items if (i % 10 === 0) { await scheduler.yield(); } } return results; } // ✅ Better: Use Web Workers const worker = new Worker('/worker.js'); worker.postMessage({ data: largeDataset }); worker.onmessage = (e) => { console.log('Results:', e.data); };

🎯 Optimize Event Handlers

Event handlers that perform heavy work can block the main thread and prevent quick response to user interactions. Optimizing these handlers is crucial for good INP scores.

Optimization Techniques:

  • Debounce high-frequency events
  • Use passive event listeners
  • Minimize work in event handlers
  • Use requestAnimationFrame for visual updates

Code Example:

// ❌ Bad: Heavy work on every scroll window.addEventListener('scroll', () => { const elements = document.querySelectorAll('.item'); elements.forEach(el => { el.style.transform = `translateY(${window.scrollY}px)`; }); }); // ✅ Good: Debounced with RAF let ticking = false; window.addEventListener('scroll', () => { if (!ticking) { window.requestAnimationFrame(() => { updateElements(); ticking = false; }); ticking = true; } }); function updateElements() { const scrollY = window.scrollY; const elements = document.querySelectorAll('.item'); elements.forEach(el => { el.style.transform = `translateY(${scrollY}px)`; }); } // ✅ Better: Debounced with timeout function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } window.addEventListener('resize', debounce(handleResize, 250));

🌳 Minimize DOM Complexity

Large DOM trees and complex CSS selectors can slow down style calculations and layout, affecting page responsiveness. Keeping your DOM lean improves INP scores.

Optimization Strategies:

  • Keep DOM tree shallow
  • Use simple CSS selectors
  • Implement virtual scrolling
  • Use CSS containment

CSS Containment:

/* Use CSS containment to limit scope */ .container { contain: layout style paint; } /* Optimize for specific use cases */ .list-item { contain: layout style; } .card { contain: content; } /* Simple vs Complex selectors */ /* ❌ Bad: Complex selector */ .header .nav ul li a:hover { color: blue; } /* ✅ Good: Simple selector */ .nav-link:hover { color: blue; }

👷 Use Web Workers for Heavy Tasks

Web Workers allow you to run JavaScript in background threads, keeping the main thread free to respond to user interactions. This is perfect for heavy computations that would otherwise block the UI.

Use Cases for Web Workers:

  • Data processing and filtering
  • Image manipulation
  • Complex calculations
  • Encryption/decryption

Web Worker Example:

// main.js const worker = new Worker('/data-processor.js'); // Send data to worker worker.postMessage({ type: 'process', data: largeDataset }); // Receive results from worker worker.onmessage = (e) => { const results = e.data; updateUI(results); }; // data-processor.js self.onmessage = (e) => { if (e.data.type === 'process') { const results = heavyProcessing(e.data.data); self.postMessage(results); } }; function heavyProcessing(data) { // Heavy computation here return processedData; }

Best Tools for INP Optimization

Recommended tools to help you achieve excellent INP scores

NitroPack

All-in-one optimization platform with advanced JavaScript optimization and script deferring features.

JavaScript Optimization
Learn More
🎯

FlyingPress

WordPress-focused plugin with excellent JavaScript optimization and delay features.

Script Optimization
Learn More
📊

GTmetrix Pro

Professional performance testing with detailed INP analysis and interaction timeline.

INP Analysis
Learn More

Ready to Improve Your INP Score?

Start optimizing your Interaction to Next Paint today and provide a more responsive, user-friendly experience. Test your current INP score and get personalized recommendations.