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.