# Interaction to Next Paint: A Practical Guide to Faster UX

_2026-08-16_

Your page loads quickly. The hero image appears without drama, the layout stays in place, and Lighthouse gives you a reassuring green result. Then a customer taps the menu, nothing visibly changes, so they tap again. A shopper clicks **Add to basket**, waits through an awkward pause, and leaves before the button confirms the action.

That gap between a page that appears fast and a page that responds quickly is where **Interaction to Next Paint**, or **INP**, matters. It measures the delay users experience after they click, tap, or press a key, not just how quickly the initial page becomes visible.

For front-end teams, INP is more than another dashboard value. It points towards the code that makes a checkout, search field, navigation menu, filter panel, or product configurator feel unreliable. For performance and CRO teams, it also creates a useful testing question: does a faster response improve behaviour, or does it merely make a report look healthier?

## Why Your Fast Site Still Feels Slow to Users

A retail team might spend a sprint improving the first render of its category page. The page shell appears promptly, the product grid arrives soon afterwards, and the layout no longer jumps when images load. The team checks the usual reports and sees little reason for concern.

On a real phone, the experience tells a different story. A customer opens the filter drawer, selects a brand, and sees no immediate visual acknowledgement because JavaScript is busy processing analytics, updating the product list, and recalculating the layout. The customer taps the filter again. The second tap may undo the first action, or both taps may queue behind the same blocked main thread.

The customer doesn't describe this as “high interaction latency”. They describe it as a broken website.

### Load speed isn't interaction speed

Metrics that focus on loading can miss what happens after the page becomes visible. A page can display its main content quickly and still make every important action feel delayed. A stable layout can prevent accidental taps while offering no guarantee that a keyboard press or button click will receive prompt visual feedback.

That distinction matters because many commercial journeys depend on repeated interaction. Search suggestions need to react as someone types. A navigation control needs to open after a tap. A basket button should provide a visible state change before a longer operation finishes.

INP became an official Core Web Vital on **12 March 2024**, replacing First Input Delay as Google's responsiveness measure, as documented in Google's [Interaction to Next Paint guidance](https://web.dev/articles/inp). The change reflects a practical limitation of looking only at the first action. Users don't stop interacting after the initial page load.

> A page isn't responsive because it loaded quickly. It's responsive when the user's action produces visible feedback without an awkward wait.

By the end of this guide, you'll be able to explain what INP measures, identify the main-thread work behind a poor result, choose the right measurement tool, and connect a responsiveness fix to an experiment that tracks commercial outcomes rather than treating a metric score as the final goal.

## What Interaction to Next Paint Actually Measures

Start with a simple example. A visitor taps a collapsed navigation menu. The browser receives the tap, waits for any queued work, runs the event handler, updates the menu state, performs the necessary style and layout work, and finally paints the changed menu on screen. INP concerns the time from that interaction to the next visible update.

Google describes INP as a responsiveness metric that captures clicks, taps, and keyboard interactions across the entire visit. The reported value represents the longest observed interaction after outliers are ignored, rather than measuring the first action. The practical thresholds are **200 milliseconds or less for good**, **200 to 500 milliseconds for needs improvement**, and **above 500 milliseconds for poor**, according to [Google's Search Console Core Web Vitals documentation](https://support.google.com/webmasters/answer/9205520?hl=uk).

![An infographic explaining Interaction to Next Paint (INP) metrics with thresholds for good, fair, and poor performance.](https://cdnimg.co/3716ee4f-bd1a-44a8-ac85-c2df5af21725/e23f17d2-5df3-4964-87c7-51e05cd27330/interaction-to-next-paint-performance-metrics.jpg)

### A restaurant analogy for the browser

Think of the browser's main thread as a small restaurant kitchen. The user's tap is the order. The event handler is the kitchen preparing it. The next paint is the waiter bringing a visible dish to the table.

If the kitchen is already buried under a large JavaScript task, the order waits before preparation begins. If the handler performs too much computation, processing takes longer. If the browser must recalculate a complicated layout before painting, presentation adds another delay. INP reflects the complete wait that the customer experiences, not just the time spent inside one function.

The metric covers interactions that produce a visual update. Scrolling and passive pointer movement aren't the same kind of interaction target. A click that opens a panel, a tap that changes a selected option, or a key press that updates an input can all expose responsiveness problems.

A page may therefore look fast at first and still record a poor INP. Event handlers, main-thread work, and JavaScript that prevents rendering can delay the visual response after an action. This is why an experimentation-heavy page deserves particular scrutiny. Each testing script, analytics callback, personalisation rule, or widget adds work that may compete with the interaction the visitor is trying to complete.

For a more engineering-focused treatment of tracing and optimisation decisions, the [guide for web performance engineers](https://pagespeedplus.com/blog/interaction-to-next-paint) offers useful additional context.

> **Working definition:** INP is the page's slowest meaningful interaction response, measured from user input to the next visible paint, with the worst outlier excluded.

That definition also explains why INP can feel awkward. One page may have many pleasant interactions and one expensive filter action. The expensive action can dominate the result, even though the median experience feels fine. The metric is intentionally sensitive to the interaction that most needs attention, but engineers still need to inspect the specific action before deciding what to change.

## How INP Differs From FID, LCP, and CLS

Core Web Vitals answer different questions. Treating them as interchangeable leads teams towards the wrong fix.

**Largest Contentful Paint**, or LCP, asks when the main content becomes visible. **Cumulative Layout Shift**, or CLS, asks whether visible content moves unexpectedly. **INP** asks how quickly the interface responds after interaction. First Input Delay, or FID, focused on the first interaction's input delay, while INP examines responsiveness across the visit.

The older metric is still useful as historical context, and this [explanation of First Input Delay](https://www.otterab.com/blog/first-input-delay) helps clarify why teams familiar with FID may initially misread INP. FID and INP aren't two names for the same measurement. Their scope and timing differ.

### Core Web Vitals at a glance

| Metric | What it measures | Trigger | Good threshold |
|---|---|---|---|
| LCP | When the largest significant content becomes visible | Initial page loading | Use the current Google-defined LCP target in your reporting |
| CLS | Unexpected movement of visible page elements | Layout changes during the page lifecycle | Use the current Google-defined CLS target in your reporting |
| INP | Responsiveness from an interaction to the next paint | Click, tap, or keyboard interaction | **200 milliseconds or less** |

INP runs throughout the visit rather than stopping after the first action. That makes it particularly relevant to pages where the important work starts after loading: product selection, account setup, filtering, checkout, editing, and search.

### Why the metrics can disagree

A fast LCP doesn't make a busy event handler faster. The browser may paint a product page promptly, then spend too long processing a click that opens a variant selector. Likewise, a low CLS doesn't mean that the selected state will appear quickly. The page can remain perfectly stable while the user waits for the interface to acknowledge an action.

Debugging should follow the symptom:

1. **Check LCP when the initial content arrives late.** Look at server response, resource priority, and the work needed to display the main content.
2. **Check CLS when elements move.** Investigate dimensions, injected content, fonts, and late layout changes.
3. **Check INP when actions feel delayed.** Record the interaction, inspect the main thread, and separate input delay, handler processing, and presentation work.

A single release can improve one metric while harming another. Deferring a script may help initial loading but leave a later interaction with more queued work. Removing a layout shift may require additional rendering logic that affects responsiveness. The useful question isn't whether the page has one green score. It's whether each important stage of the user's journey responds as expected.

## Measuring INP in the Lab and in the Field

A lab test and a field measurement answer different questions. Lab testing gives you a controlled place to reproduce a suspected interaction. Field data shows how the page behaves across real devices, browsers, networks, and user journeys.

![A diagram comparing lab-based synthetic testing and field-based real user monitoring for measuring INP performance metrics.](https://cdnimg.co/3716ee4f-bd1a-44a8-ac85-c2df5af21725/38f75813-77c0-4e7d-835a-21fe7b39df3d/interaction-to-next-paint-performance-measurement.jpg)

### Use the lab to find the cause

Chrome DevTools' Performance panel is the hands-on starting point. Record a representative journey, interact with the page, and inspect the **Interactions** track alongside the **Main** track. You're looking for the interaction that takes longest and the tasks that occupy the main thread around it.

Lighthouse can provide a quick audit and a repeatable baseline, although a synthetic run won't reproduce every real user action. Use it to detect regressions and compare controlled changes, not as a substitute for production evidence.

The `web-vitals` JavaScript library can collect INP in the browser and send values to your analytics system. That allows you to segment results by page, device category, route, interaction type, or release. The exact dimensions depend on your instrumentation, but the principle is simple: don't settle for one site-wide number if you need to know which journey is slow.

### Use the field to understand the experience

The Chrome User Experience Report, or CrUX, aggregates field observations from eligible real-world usage. PageSpeed Insights combines lab-style diagnostics with field information where available, which makes it useful for checking whether a local improvement corresponds with what users experience.

A sensible workflow looks like this:

- **Start with a hunch:** Identify the menu, search box, filter, or checkout control that users describe as slow.
- **Reproduce in DevTools:** Record the interaction and inspect the main-thread timeline.
- **Instrument the journey:** Collect INP and useful page or interaction context from production.
- **Compare segments:** Separate device and route patterns where your data supports that analysis.
- **Validate the release:** Watch field trends after shipping rather than judging the patch from one local run.

Teams building a broader observability practice can use this [performance monitoring guide](https://www.otterab.com/blog/performance-monitoring) to think about how browser performance data fits with the rest of their operational signals.

Lab data explains **why** an interaction is slow. Field data tells you **where and for whom** the problem matters. You need both before prioritising a fix.

## The Most Common Causes of a Poor INP

The common assumption is that a heavy page is automatically a slow page. That isn't precise enough. INP is usually damaged by work that blocks the browser at the wrong moment, especially around a user action.

A UK-wide CrUX analysis of **11,386 highly visited websites across 23 sectors** found that, in March 2024, only the Law and Government sector averaged a passing INP score, at **149 milliseconds**. Gambling averaged **370 milliseconds**, while News and Media averaged **297 milliseconds**, according to the [UK INP sector analysis](https://starukh.com/inp-study-uk/). Those results don't identify one universal culprit, but they show why responsiveness deserves attention beyond a small set of poorly built sites.

![An infographic showing three main causes of poor Interaction to Next Paint: heavy main thread, third-party scripts, and layout thrash.](https://cdnimg.co/3716ee4f-bd1a-44a8-ac85-c2df5af21725/f9728eb2-c9bd-4291-a0c1-3966cd81a5fe/interaction-to-next-paint-inp-causes.jpg)

### Heavy main-thread work

JavaScript runs on the main thread alongside event handling, style calculation, layout, painting, and other browser tasks. A click handler that parses a large response, rebuilds a complex component tree, or updates many DOM nodes can keep the browser from painting the feedback the user expects.

Long tasks are particularly disruptive. A task that runs for a long time can delay several inputs behind it, so the user experiences the whole queue rather than the duration of the function they initiated.

### Third-party scripts

Analytics, chat, consent tools, advertising tags, personalisation systems, and embedded widgets often run outside the feature the user is trying to use. They can still consume main-thread time, attach expensive listeners, trigger DOM work, or schedule callbacks after an interaction.

Audit third parties by purpose and timing. A script that isn't needed for the first user action shouldn't compete with that action, and a widget that nobody uses may not justify its ongoing cost. For framework-specific decisions, this resource on [performance optimisation for Vue developers](https://getdom.studio/blog/performance-optimization) provides relevant implementation context.

### Layout thrashing and framework overhead

Layout thrashing occurs when code writes to the DOM and then immediately reads layout information, forcing the browser to recalculate before the next operation. Repeating that pattern inside a loop can turn a small update into a costly sequence of recalculations.

Large DOM trees multiply the work needed to apply changes. Framework hydration can add another burst of main-thread activity, particularly when a page becomes interactive while the user is already trying to tap it. Render-blocking JavaScript can create the same practical outcome, even if the script isn't part of the clicked component.

Device differences matter too. A page that feels acceptable on a developer workstation may struggle on a lower-powered mobile device. Check [device compatibility considerations](https://www.otterab.com/blog/device-compatibility) before assuming a desktop trace represents the full audience.

The evidence challenges a simple “reduce page weight” approach. Start with the interaction trace, identify the work that blocks its next paint, and then remove, split, defer, or relocate that work.

<iframe width="100%" style="aspect-ratio: 16 / 9;" src="https://www.youtube.com/embed/cmtfM4emG5k" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>

## Prioritised Fixes That Actually Move the Metric

Fixes should follow the trace, not a generic checklist. The highest-value change is usually the one that removes work from the interaction's critical path.

### Priority one, remove avoidable work

Begin with code that doesn't need to run. Remove unused third-party tags, delay non-essential widgets until they're requested, and prevent analytics callbacks from rebuilding interface state. Code-split routes and features so the browser doesn't parse and execute every capability before the visitor needs it.

A useful review question is, “What must happen before the user can see feedback?” Keep that path narrow. A basket button may need to update its selected state immediately, while a secondary recommendation request can happen later.

### Priority two, make handlers yield

A large handler doesn't become responsive merely because it has a clear function name. Break computation into smaller pieces and return control to the browser between them. Where browser support allows, `scheduler.yield()` can help a long operation give input and rendering opportunities back to the main thread. Feature-detect it and provide a suitable fallback rather than assuming every browser exposes the same scheduling API.

Debounce input that doesn't need to run for every keystroke. Search suggestions, validation, and filtering often produce redundant work when each event triggers parsing, rendering, and network activity. Debouncing can reduce that pressure, but don't use it to hide a missing visual acknowledgement. Show the input state promptly, then schedule expensive follow-up work.

### Priority three, avoid forced layout work

Batch DOM reads separately from DOM writes. Read the measurements you need, apply changes in a group, and avoid repeatedly asking the browser for layout information after each mutation. This is especially important in loops that resize, position, or measure many elements.

CSS can also help. Use `content-visibility` where off-screen content doesn't need immediate rendering, and apply `will-change` selectively for elements that benefit from compositor treatment. These tools aren't universal cures. Excessive promotion or hiding the wrong content can create memory and rendering costs elsewhere.

### Priority four, move suitable computation away

Parsing, filtering, or transforming a substantial data set may belong in a Web Worker rather than on the main thread. A worker won't remove the need to update the interface, and message passing has its own cost, but it can prevent computation from blocking input and painting.

A typical commerce team might discover that a chat widget runs unnecessary work during product selection. Removing that widget could make a trace substantially cleaner. Treat that scenario as a debugging pattern, not a promised result. The correct gain depends on the widget, the device, the interaction, and the rest of the page.

> **Engineering rule:** Give the user an immediate, truthful state change first. Do expensive work afterwards, or move it somewhere that can't block the next paint.

After each change, record the same journey under comparable conditions. A smaller script bundle isn't proof of a better interaction, and a better interaction trace isn't proof that the business journey improved. Both need measurement.

## Validating Improvements With Lab Tests and Live Experiments

A performance fix has two jobs. It should reduce the work that delays the next paint, and it should improve the experience or outcome that justified the work.

Start locally. Capture a DevTools Performance trace before the change, repeat the same interaction afterwards, and inspect whether the blocking task, processing time, or presentation delay has changed. Re-run Lighthouse for a controlled comparison, but keep the interaction itself in view because a general audit can miss the feature that matters most.

![A notepad showing four steps for validating web performance improvements through lab tests and field experiments.](https://cdnimg.co/3716ee4f-bd1a-44a8-ac85-c2df5af21725/dd8ff9e7-20af-4533-a325-50fd4b4a4805/interaction-to-next-paint-performance-validation.jpg)

### Connect the metric to the decision

Production monitoring answers whether the improvement survives real conditions. Watch field INP by page and journey, compare releases, and look for regressions after adding scripts or interface complexity. CrUX can provide an aggregated view, while your own real-user instrumentation can expose the interaction and product context that a broad dataset can't.

Then test the business hypothesis. An A/B test can compare a responsiveness change against the existing experience, provided the experiment itself doesn't introduce the same main-thread burden you're trying to remove. The relevant outcome might be conversion rate, completed checkout, revenue, or average order value, depending on the journey.

A small INP improvement that users barely notice still needs to justify its implementation risk. Conversely, a change that improves a high-friction control may matter commercially even when the site-wide metric moves only modestly. Otter A/B is one option for running these tests. Its SDK is designed to be lightweight, and the platform can associate variants with goals, purchases, average order value, and revenue so teams can judge performance work against business results.

Use a repeatable decision loop:

1. **Ship the fix:** Keep the code change focused and document the affected interaction.
2. **Measure the field:** Check whether real-user responsiveness changes after release.
3. **Run the experiment:** Compare the revised experience with the existing one.
4. **Decide on evidence:** Keep, revise, or roll back based on both user performance and commercial outcomes.

INP gives engineers a precise place to investigate. Experimentation tells the wider team whether the investigation produced value.

---

Otter A/B helps teams test interface and performance changes while tracking goals, purchases, average order value, and revenue by variant. Visit [Otter A/B](https://www.otterab.com) to connect INP improvements with live experiment results and make the next optimisation decision using both responsiveness data and business evidence.

---

Canonical page: https://www.otterab.com/blog/interaction-to-next-paint
