Understanding INP: The Complete Guide to Interaction to Next Paint
Master Interaction to Next Paint (INP), the Core Web Vital that replaced FID. Learn about INP's history, how it measures responsiveness, why FID was retired, and how to optimize your INP score.
What is Interaction to Next Paint (INP)?
Interaction to Next Paint (INP) is a Core Web Vital that measures page responsiveness. Specifically, it tracks the latency between when a user interacts with your page (clicking, tapping, or pressing a key) and when the browser displays the visual feedback of that interaction.
Think of it this way: when you click a button on a website, you expect something to happen immediately. INP measures how long it takes from your click until you see the response. If there’s a noticeable delay, the site feels sluggish and unresponsive.
Unlike its predecessor FID (First Input Delay), which only measured the first interaction, INP measures all interactions throughout the user’s session and reports a value that represents the overall responsiveness of the page.
What Counts as an Interaction?
INP considers these types of user interactions:
- Clicks (mouse or trackpad)
- Taps (touchscreen devices)
- Key presses (physical or on-screen keyboards)
Not included:
- Scrolling
- Hovering
- Pinch-to-zoom
- Mouse movement
These excluded interactions are typically handled differently by browsers and don’t have discrete “start” and “end” points that can be measured reliably.
The Three Phases of an Interaction
Every interaction INP measures consists of three phases:
- Input Delay - Time from when the user interacts until event handlers start running
- Processing Time - Time spent running event handlers
- Presentation Delay - Time from when handlers complete until the browser paints the result
Total INP = Input Delay + Processing Time + Presentation Delay
INP Thresholds
| Rating | Latency |
|---|---|
| Good | ≤ 200 milliseconds |
| Needs Improvement | 200 - 500 milliseconds |
| Poor | > 500 milliseconds |
To provide a good experience, Google recommends that the 75th percentile of page visits have an INP of 200 milliseconds or less.
The History of Responsiveness Metrics
The Early Days: No Standard Metric
In the early web, there was no standard way to measure how responsive a page felt. Developers relied on subjective testing or crude measurements like “time to interactive,” which had various definitions.
First Input Delay (FID): 2018-2024
Introduction (2018)
Google introduced First Input Delay in 2018 as part of their early web vitals work. FID measured the delay between a user’s first interaction and when the browser could begin processing that interaction.
The Promise of FID
FID was innovative because it:
- Focused on real user experience, not synthetic benchmarks
- Could be measured with minimal performance overhead
- Correlated with user frustration from unresponsive pages
FID Becomes a Core Web Vital (2020)
When Google announced Core Web Vitals in May 2020, FID was chosen as the responsiveness metric alongside LCP and CLS.
FID Thresholds:
- Good: ≤ 100ms
- Needs Improvement: 100-300ms
- Poor: > 300ms
The Limitations of FID
As websites evolved and the Chrome team gathered more data, FID’s limitations became apparent:
Problem 1: Only Measures First Interaction
FID only captured the very first interaction. If a user’s first click was responsive but subsequent interactions were slow, FID wouldn’t reflect that. Users might have a great FID but a terrible overall experience.
Problem 2: Ignored Processing Time
FID measured only the delay before handlers ran, not how long the handlers themselves took. A page could have a great FID but still feel sluggish if the event handlers were slow.
Problem 3: Ignored Presentation Delay
FID didn’t account for time between when handlers finished and when the visual update appeared. Complex DOM changes or forced layout recalculations weren’t captured.
Problem 4: Many Sites Had “Perfect” FID
By 2023, over 90% of sites had good FID scores. This sounds positive, but it meant FID was no longer differentiating between truly responsive and merely adequate sites.
Total Blocking Time (TBT): A Lab Alternative
While FID was the field metric, developers used Total Blocking Time (TBT) in lab environments. TBT measures the total time the main thread was blocked during page load. While useful, TBT didn’t measure actual user interactions.
INP Development (2022-2024)
May 2022: INP Introduced as Experimental
Google announced INP as an experimental metric, available in Chrome UX Report and web-vitals library. They encouraged developers to start measuring and optimizing for it.
Design Goals for INP:
- Measure ALL interactions, not just the first
- Include the full interaction latency (delay + processing + presentation)
- Report a single value representing overall responsiveness
- Be measurable in the field with low overhead
February 2024: INP Promoted to Pending
Google announced INP would replace FID as a Core Web Vital in March 2024, giving developers a month to prepare.
March 12, 2024: INP Becomes Core Web Vital
INP officially replaced FID. All Core Web Vitals tools, reports, and ranking signals now use INP instead of FID.
Why the 200ms Threshold?
Research shows that delays under 100ms feel instantaneous to users. Between 100-300ms, users notice the delay but don’t lose their sense of cause and effect. Beyond 300ms, the delay becomes frustrating.
Google chose 200ms as the “good” threshold because:
- It provides buffer for the full interaction lifecycle
- It’s achievable for well-optimized sites
- It correlates with positive user experience metrics
Why INP Matters
Real-World Responsiveness
INP captures what users actually experience. A site might look fast on paper but feel sluggish in practice. INP reveals these hidden responsiveness problems.
Business Impact
Poor responsiveness directly affects business metrics:
Bing Study: A 100ms increase in page latency resulted in a 0.6% decline in revenue.
Amazon: Found that every 100ms of latency cost them 1% in sales.
Google Research: Pages with better INP scores have lower bounce rates and longer session durations.
Competitive Advantage
Many sites that passed FID will fail INP. This reset creates opportunities for sites that optimize proactively.
SEO Ranking Signal
INP is now part of Core Web Vitals, which influences Google rankings. While not the most important factor, it can be a tiebreaker between otherwise equal pages.
How INP is Calculated
The Measurement Process
- Every interaction is measured - Each click, tap, or keypress is tracked
- Full latency is captured - Input delay + processing + presentation
- Worst interaction is identified - Usually the slowest interaction
- Statistical adjustment - For pages with many interactions, an “almost worst” value is used
The 75th Percentile
INP reports the 75th percentile of interaction latencies. This means:
- 75% of users experience this latency or better
- It accounts for outliers and slow networks
- It represents what most users actually experience
High Interaction Pages
For pages with many interactions (like complex web apps), INP uses a slight adjustment to avoid being overly influenced by single outliers. Specifically, for every 50 interactions, one additional slow interaction is ignored.
Common Causes of Poor INP
1. Long JavaScript Tasks
The browser’s main thread can only do one thing at a time. Long JavaScript tasks block the thread and delay interaction handling.
Symptoms:
- Long tasks (>50ms) visible in DevTools Performance panel
- High Total Blocking Time
- Visible delay after clicking
Solutions:
- Break long tasks into smaller chunks using
setTimeoutorrequestIdleCallback - Move work off the main thread with Web Workers
- Defer non-critical JavaScript
2. Heavy Event Handlers
Event handlers that do too much work cause high processing time.
Symptoms:
Solutions:
- Optimize event handler code
- Use virtualization for large lists
- Debounce or throttle frequent events
- Move expensive operations to Web Workers
3. Excessive DOM Size
Large DOM trees make updates expensive and increase presentation delay.
Symptoms:
-
1500 DOM elements
- Deep nesting (>32 levels)
- Slow layout calculations
Solutions:
- Reduce DOM size
- Use virtualization for long lists
- Simplify nested structures
- Avoid inline styles that trigger layout
4. Forced Synchronous Layouts
Reading layout properties after making style changes forces the browser to recalculate layout immediately.
Symptoms:
- Layout thrashing warnings in DevTools
- Patterns like read-style-read-style
Solutions:
- Batch DOM reads and writes
- Use CSS transforms instead of layout properties
- Avoid
offsetWidth,offsetHeightin loops
5. Third-Party Scripts
External scripts can block the main thread unexpectedly.
Symptoms:
- Third-party scripts in flame charts during interactions
- Analytics or ad scripts running during user actions
Solutions:
- Audit third-party scripts
- Load non-critical scripts asynchronously
- Use Partytown or similar for off-main-thread execution
Optimizing INP: Proven Strategies
Break Up Long Tasks
// Before: One long task
function processAllItems(items) {
items.forEach(item => processItem(item)); // Blocks for entire duration
}
// After: Yield to the browser periodically
async function processAllItems(items) {
for (const item of items) {
processItem(item);
// Yield every 5ms to allow interactions
if (performance.now() - startTime > 5) {
await scheduler.yield(); // Chrome 129+
// Or: await new Promise(resolve => setTimeout(resolve, 0));
startTime = performance.now();
}
}
}
Use scheduler.yield() (Modern Browsers)
async function handleClick() {
// Do critical work first
updateButtonState();
// Yield to let the browser paint
await scheduler.yield();
// Continue with less critical work
sendAnalytics();
updateRelatedContent();
}
Optimize Event Handlers
// Before: Heavy handler
button.addEventListener('click', async () => {
const data = await fetchData(); // Network delay
processAllData(data); // Heavy processing
renderResults(data); // Heavy DOM updates
});
// After: Optimized handler
button.addEventListener('click', async () => {
// Immediate visual feedback
button.classList.add('loading');
// Move heavy work off main thread
const worker = new Worker('/process-worker.js');
const data = await fetchData();
worker.postMessage(data);
worker.onmessage = (e) => {
// Efficient rendering
requestAnimationFrame(() => {
renderResults(e.data);
button.classList.remove('loading');
});
};
});
Virtualize Long Lists
// Before: Render all items
function renderList(items) {
items.forEach(item => {
const el = createItemElement(item);
container.appendChild(el);
});
}
// After: Only render visible items
// Use libraries like react-window, vue-virtual-scroller, or lit-virtualizer
import { FixedSizeList } from 'react-window';
<FixedSizeList
height={500}
itemCount={items.length}
itemSize={50}
>
{({ index, style }) => (
<div style={style}>{items[index].name}</div>
)}
</FixedSizeList>
Debounce Frequent Interactions
// Debounce search input
const debouncedSearch = debounce(performSearch, 300);
searchInput.addEventListener('input', debouncedSearch);
function debounce(fn, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), delay);
};
}
Use CSS for Animations
/* Avoid: JavaScript-driven animations that block main thread */
/* Use: CSS animations with GPU-accelerated properties */
.animated {
transition: transform 0.3s ease, opacity 0.3s ease;
}
.animated:hover {
transform: scale(1.1);
opacity: 0.8;
}
Measuring and Debugging INP
Tools for INP Analysis
Chrome DevTools
- Performance panel: Record user interactions
- Look for long tasks during interactions
- Identify slow event handlers
PageSpeed Insights
- Shows INP in field data (if available)
- Identifies slow interactions
- Provides optimization suggestions
Web Vitals Extension
Using the web-vitals Library
import {onINP} from 'web-vitals';
onINP(metric => {
console.log('INP:', metric.value, 'ms');
console.log('Interaction type:', metric.entries[0]?.name);
// Send to analytics
sendToAnalytics({
name: 'INP',
value: metric.value,
rating: metric.rating, // 'good', 'needs-improvement', 'poor'
interaction: metric.entries[0]?.name,
});
});
The Interaction Timeline
When debugging a slow interaction, look for:
- Input delay - Is the main thread blocked when user clicks?
- Event handler - Is the handler code itself slow?
- Style/Layout - Is the browser recalculating styles?
- Paint - Is painting taking too long?
INP Debugging Checklist
- Use the web-vitals library to measure INP in production
- Identify your slowest interactions using DevTools
- Check for long tasks (>50ms) during interactions
- Review event handler code for heavy operations
- Look for forced synchronous layouts
- Audit third-party scripts blocking the main thread
- Check DOM size and complexity
- Test on real mobile devices, not just desktop
- Use Chrome’s Performance panel Interactions track
Migrating from FID to INP
Key Differences
| Aspect | FID | INP |
|---|---|---|
| Interactions measured | First only | All |
| What’s measured | Input delay only | Full latency |
| ”Good” threshold | ≤100ms | ≤200ms |
| Typical site score | Usually good | Often needs work |
If You Had Good FID
Don’t assume you’ll have good INP. Many sites that passed FID fail INP because:
- Subsequent interactions are slower than the first
- Processing and presentation time weren’t captured by FID
- Complex interactions reveal responsiveness issues
Prioritization Strategy
- Find your worst interactions - Use field data and DevTools
- Focus on common interactions first - Buttons, links, form inputs
- Address the biggest delays - Long tasks, heavy handlers
- Test on representative devices - Mobile phones are often worse
Common INP Mistakes to Avoid
1. Only Testing the First Interaction
Unlike FID, INP considers all interactions. Test scrolling, clicking multiple buttons, filling forms, not just the first action.
2. Ignoring Mobile Performance
Mobile devices have slower processors. An interaction that feels instant on desktop might be sluggish on mobile.
3. Blocking on Analytics
Sending analytics synchronously during interactions adds delay. Always send analytics asynchronously or defer it.
4. Not Using Browser Scheduler APIs
Modern browsers offer scheduler.yield() and scheduler.postTask() to help manage main thread work. Use them.
5. Over-Relying on Virtualization
Virtualization helps with long lists but adds complexity. Sometimes simplifying the DOM is better than adding virtualization overhead.
Conclusion
Interaction to Next Paint represents a significant evolution in how we measure web responsiveness. By capturing the full lifecycle of all interactions, not just the first, INP provides a much more accurate picture of how users experience your site.
The transition from FID to INP is an opportunity. Sites that invest in responsiveness optimization now will gain advantages as competitors struggle to meet the new standard.
Remember: responsiveness isn’t just about metrics. Every millisecond of delay is friction between your users and their goals. Fast interactions build trust, encourage engagement, and create the kind of smooth experiences that keep users coming back.
Related Articles
- Website Performance Guide - Complete guide to Core Web Vitals and optimization strategies
- Core Web Vitals: Understanding Google’s Vital Signals - Overview of all Core Web Vitals
- Understanding LCP: The Complete Guide to Largest Contentful Paint - Master loading performance
- Understanding CLS: The Complete Guide to Cumulative Layout Shift - Achieve visual stability
- What is a Website Audit? - Learn why performance audits matter
FAQs
1. What’s a good INP score? 200 milliseconds or less is “good.” Between 200-500ms needs improvement, and over 500ms is poor.
2. Why did my INP get worse when FID was replaced? INP measures more interactions and more of each interaction’s lifecycle. Sites that passed FID often reveal hidden responsiveness problems under INP.
3. How is INP different from TBT (Total Blocking Time)? TBT measures main thread blocking during page load in lab conditions. INP measures actual interaction latency from real users throughout their session.
4. Can I still measure FID? Yes, for historical comparison, but FID is no longer a Core Web Vital and isn’t used in rankings.
5. Why does my INP vary between visits? INP depends on which interactions users perform, device capability, and network conditions. Field data shows the 75th percentile to account for this variation.
6. Should I optimize for the worst interaction or average? Focus on your worst common interactions first. The 75th percentile means most users encounter your slowest interactions, so improving them has the biggest impact.