Перейти к содержанию
A hand pressing a brass button set into a pale limestone wall
R&D

INP and Core Web Vitals: what actually moves the needle?

Коротко

Interaction to Next Paint is the Core Web Vital most sites now struggle with on mobile. What the field data says, what causes slow interactions, how to measure them with CrUX and RUM, and the fixes that reliably work.

17 мин чтения

Interaction to Next Paint (INP) measures how quickly a page visibly responds when someone clicks, taps or types, and a good score is 200 milliseconds or less for at least three in four visits. What moves it is almost always main-thread work: long JavaScript tasks running when the user acts, heavy event handlers, and expensive rendering after them. Measure it in the field with real-user data, find the specific slow interactions, then break up long tasks, defer third-party code and keep the DOM and re-renders small.

This write-up collects what Google's documentation, the HTTP Archive and published case studies say about INP and the other two Core Web Vitals, and turns it into a working method: how to measure, how to diagnose, which fixes are worth the effort and which are not. It also covers, carefully, how much Core Web Vitals matter for search rankings, because that question drives a lot of wasted work.

The three Core Web Vitals and their thresholds

Google's Core Web Vitals are three field metrics, each covering one aspect of experience: Largest Contentful Paint (LCP) for loading, Interaction to Next Paint (INP) for responsiveness, and Cumulative Layout Shift (CLS) for visual stability. Each is assessed at the 75th percentile of page loads, separately for mobile and desktop. A page passes only if all three meet the good threshold at that percentile.

MetricWhat it measuresGoodNeeds improvementPoor
LCPWhen the largest image or text block in the viewport is rendered2.5 s or less2.5 to 4 sOver 4 s
INPLatency of clicks, taps and key presses across the whole visit200 ms or less200 to 500 msOver 500 ms
CLSHow much visible content moves unexpectedly0.1 or less0.1 to 0.25Over 0.25
Core Web Vitals thresholds, assessed at the 75th percentile of real page loads (sources: web.dev pages on vitals, INP and CLS)

INP replaced First Input Delay (FID) as the responsiveness metric. Google announced the change in May 2023 and made it in March 2024. FID only measured the delay before the first interaction's handlers started; it ignored how long those handlers ran, how long the browser took to paint the result, and every interaction after the first. That made FID easy to pass and not very informative. INP is harder because it looks at the whole visit, which matters: Chrome usage data shows that 90% of a user's time on a page is spent after it loads.

How INP is calculated

The browser observes every click, tap and key press during a visit. Hovering, scrolling and zooming do not count. For each interaction it measures the time from the input to the next frame painted on screen. At the end of the visit, the page's INP is the slowest interaction, except that on pages with many interactions the browser discards one of the highest for every 50 interactions, so a single freak outlier on a long session does not define the score. Across all visits, the value at the 75th percentile is what CrUX and Search Console report.

Every interaction's latency splits into three phases, and knowing which one dominates tells you what to fix.

  • Input delay: from the user's input until event handlers start running. It grows when the main thread is busy with something else at that moment: script evaluation during page load, timers, a previous interaction's work, or a third-party tag.
  • Processing duration: the time the event handlers themselves take. Large state updates, synchronous re-renders of big component trees and expensive calculations live here.
  • Presentation delay: from the end of the handlers until the next frame is painted. Style recalculation, layout and paint for a large or complex DOM, and forced synchronous layouts, are the usual causes.

Google's guide to optimising INP is organised around exactly these three phases, and it is the best single reference on the topic. Our main addition is about order: find out which phase is slow in the field before touching code, because the fixes for each are different and effort spent on the wrong phase does nothing.

What the field data says today

The HTTP Archive's 2025 Web Almanac performance chapter, based on July 2025 Chrome UX Report data, gives a clear picture. On desktop, 97% of sites have good INP. On mobile the figure is 77%, up from 74% a year earlier. Only 48% of sites pass all three Core Web Vitals on mobile, against 56% on desktop. LCP is the weakest metric on mobile at 62% good.

Two details in the same chapter are worth noting. First, INP is worse on secondary pages than on home pages: 80% of mobile home pages have good INP against 69% of other pages, which fits the intuition that product listings, search results, filters and forms carry more interaction-heavy JavaScript than a landing page. Second, the most visited sites do not do better: only 63% of the top 1,000 sites have good mobile INP, lower than the long tail. Big, feature-rich sites tend to carry more scripts and more complex interfaces.

The practical message: if you test on a fast laptop, INP will look fine. Your users on mid-range Android phones are where the problem lives, and that is also where most of your traffic may be.

What causes poor INP

Almost every slow interaction comes back to one fact: the browser's main thread does one thing at a time. A long task is any task over 50 milliseconds, and while it runs the page cannot respond to input or paint a new frame. The recurring sources are these.

Long tasks during and just after load

Users interact earlier than developers assume: they tap a menu or a cookie banner while scripts are still being parsed and evaluated. Large JavaScript bundles, framework start-up and hydration all create long tasks in that window. Interactions that land on them get a large input delay even if their own handlers are cheap. The web-vitals library reports the document's load state for each slow interaction, which makes this pattern easy to spot.

Third-party scripts

Tag managers, analytics, A/B testing, chat widgets, consent tools, ad scripts and embedded video all run on the same main thread as your own code. The 2024 Web Almanac third-parties chapter found third parties on 92% of pages, with a median of 27 per page across the top million sites and 66 for the top 1,000. You did not write that code and often cannot change it, but you can decide when and whether it loads.

Heavy event handlers and re-renders

A click that updates a global store, which re-renders half the page, which recomputes derived data synchronously, can easily take hundreds of milliseconds on a phone. Typing into a search box that filters a large list on every keystroke is the classic case. So is a filter panel on a product listing page that re-renders every product card.

Large DOMs and expensive rendering

After the handlers run, the browser has to recalculate styles, lay out and paint. The cost scales with the size and complexity of what changed. Google's article on DOM size and interactivity notes that Lighthouse starts warning at 800 DOM nodes and fails the audit at 1,400, and that interactions which insert or remove elements are the most important case for INP. Mega-menus rendered in full on every page, hidden modals kept in the DOM and long unvirtualised tables are common offenders.

Layout thrashing

Reading a layout property such as an element's height straight after changing styles forces the browser to compute layout synchronously, in the middle of your script. Doing it in a loop, write then read then write then read, multiplies the cost. It is easy to introduce in animation, measurement and drag-and-drop code, and it shows up in profiles as forced reflow.

Measuring INP in the field

INP is a field metric. It depends on what real people click, on their devices, at the moment they click. Lab tools cannot reproduce that fully, so start with field data and use the lab to reproduce what the field points to.

CrUX and PageSpeed Insights

The Chrome UX Report collects anonymised metrics from Chrome users who have opted in. Data is a 28-day rolling average, updated daily, split into phone, tablet and desktop. Pages and origins only appear if they are publicly discoverable and have enough traffic, and Chrome on iOS and other Chromium browsers do not contribute. PageSpeed Insights shows CrUX data at the top and a Lighthouse lab run below. Use it to see whether you have a problem and on which template; it will not tell you which interaction is slow.

Search Console

The Core Web Vitals report uses CrUX data and groups URLs with a similar experience, such as all product pages, rating each group by its worst metric. It is the best view of which templates fail across a whole site. After a fix, starting validation opens a 28-day monitoring window on the CrUX data; it does not trigger recrawling, and you cannot speed it up.

Your own RUM

Real-user monitoring is the only source that tells you which element was interacted with, which phase was slow and which script was running. Google's open-source web-vitals library reports INP, LCP and CLS from real sessions; its attribution build adds the interaction target, the input delay, processing and presentation times, the page's load state and any overlapping long animation frames. Send the data with sendBeacon when the page is hidden. Commercial RUM products offer the same with dashboards.

Lab tools

Lighthouse cannot measure INP on a page load, so it reports Total Blocking Time instead. Google describes TBT as a reasonable lab proxy for INP but not a substitute, with a target under 200 milliseconds on average mobile hardware. Lighthouse's user-flow mode and the Chrome DevTools Performance panel let you record real interactions with CPU throttling, which is how you reproduce a slow interaction the field data has found.

Lab TBT is worth watching because it is cheap to run on every build, but it is a different measurement. The 2025 Web Almanac reports a median mobile TBT of 1,916 ms in its lab runs, far above the 200 ms target, while 77% of sites still have good INP in the field. Lab runs throttle the CPU and count all blocking time after first paint, whether a user would have interacted then or not. Treat TBT as an early warning in CI, and field INP as the score that counts.

Long Animation Frames: finding the culprit script

The Long Animation Frames API (LoAF) is the most useful diagnostic addition of recent years. Instead of reporting long tasks in isolation, it reports frames whose rendering was delayed by more than 50 ms, and attributes the time to scripts: the source URL, the function, how it was invoked (an event listener, a timer, a promise) and how much time it spent in forced style and layout. That last field identifies layout thrashing directly. Collected through the web-vitals attribution build, it lets you say not just that the filter button is slow, but that a particular analytics script was running when people pressed it. LoAF is available in Chrome and Edge; Firefox and Safari do not support it.

Safari and Firefox now report INP too

Until recently, INP was a Chromium-only measurement. In December 2025, with Safari 26.2, Google announced that LCP and INP are now Baseline across all major browsers. That means your own RUM can now see responsiveness for iPhone users, which CrUX never covered. Two caveats: Firefox and Safari end the measurement at a slightly earlier point in the paint pipeline than Chrome, so values differ by small amounts, and CLS is still Chromium-only. CrUX itself still reports Chrome users only.

Fixes that reliably improve INP

These are the changes that most often move field INP, roughly in the order we would try them once the data has pointed at a page and an interaction.

1. Do the visible update first, then yield

INP stops counting at the next paint. So in an event handler, make the change the user needs to see (open the menu, show the spinner, tick the checkbox), then yield to the main thread, then do the rest: analytics calls, saving to storage, recalculating totals, prefetching. The browser paints in the gap. Google's long tasks guide recommends scheduler.yield() where it exists, because its continuation runs before other queued work such as third-party tasks, with a fallback to a promise wrapped around setTimeout. scheduler.yield() is supported in Chrome and Edge from version 129 and Firefox from 142, but not Safari, so ship the fallback. Older advice to use isInputPending() is now deprecated.

2. Break up long tasks everywhere, not just in handlers

Input delay is caused by other people's tasks, so the fix often lives far from the slow button. Long initialisation code, large JSON parsing, client-side rendering of lists and analytics batching can all be chunked so that no single task runs much past 50 ms. Batch many small jobs and yield every 50 ms or so rather than after each one, since yielding has a cost. Move genuinely heavy computation, such as parsing a large file or searching a big dataset, to a web worker, which has its own thread.

3. Debounce and localise state

For search boxes, sliders and scroll-driven updates, debounce the expensive work and keep the immediate response small. The redBus case study on web.dev is a good illustration: the team debounced a scroll handler, cut each lazy-load batch from 30 results to 10, and kept a text input's state local, syncing it to the global Redux store on blur instead of on every change. The company reported a 72% INP improvement on that page and a 7% increase in sales. Those are the company's own figures, and sales depend on much more than INP, but the techniques are generic.

4. Use your framework's scheduling features

In React, useTransition marks a state update as non-urgent: React renders it in the background and interrupts it if the user does something more urgent, such as typing. Wrapping the expensive part of an update, like re-rendering a results grid after a filter change, in a transition keeps the input itself responsive. React's documentation is explicit that transitions cannot drive a controlled text input; keep the input's own state synchronous and defer the derived rendering with a second state variable or useDeferredValue. Memoising expensive components and avoiding context providers that re-render the whole tree on every change help in the same direction. Vue, Svelte and Angular have their own equivalents.

5. Shrink and stream the HTML

Rendering large amounts of HTML with client-side JavaScript produces one long task. Server-rendered, streamed HTML is parsed in chunks, which yields to the main thread automatically. Server-render what you can, hydrate only what needs to be interactive, and keep client-rendered DOM small. In frameworks such as Next.js, keeping most components as server components and pushing client code to the interactive leaves of the tree reduces the JavaScript that has to start up before the page responds.

6. Reduce rendering work

Flatten unnecessary wrapper elements, render menus and modals only when opened, and virtualise long lists and tables. The CSS property content-visibility: auto lets the browser skip layout and paint for off-screen sections; in Google's example, initial rendering time fell from 232 ms to 30 ms. Pair it with contain-intrinsic-size so the scrollbar does not jump. It became Baseline across browsers in September 2025. To avoid layout thrashing, batch DOM reads before writes, and animate with transform and opacity rather than properties that trigger layout.

7. Take control of third-party scripts

Audit every tag: who owns it, what it is for, and whether anyone still uses its data. Remove the ones nobody can justify. Load the rest as late as their purpose allows. Chat widgets and video embeds are good candidates for facades: a lightweight static element that loads the real widget only when the user interacts, with the trade-off that features such as unread badges appear later. Frameworks help here too; the Next.js Script component offers afterInteractive for tag managers and analytics and lazyOnload for chat and social widgets. Moving third-party scripts into a web worker with tools such as Partytown can work, but it is experimental and not every script is compatible.

The Economic Times case study combines most of these fixes: deferring non-critical work, lazy loading third-party libraries, rendering menu items only on click (removing about 1,200 DOM nodes), moving third-party work to web workers with Partytown, and upgrading React and Next.js. The publisher reported origin INP falling from over 1,000 ms to 257 ms, and on the topic pages it migrated first, a 50% fall in bounce rate. Again, these are self-reported figures from a single site.

Slow phaseUsual causeFirst fixes
Input delayMain thread busy when the user acts: start-up scripts, hydration, timers, third-party tagsBreak up long tasks; defer or remove third parties; reduce JavaScript at start-up
Processing durationEvent handlers do too much: global state updates, large re-renders, synchronous calculationsVisible update first, then yield; debounce; transitions; move heavy work to a worker
Presentation delayExpensive style, layout and paint after the update: large DOM, client-rendered HTML, forced layoutsSmaller DOM; content-visibility; render on demand; batch reads and writes
Slow mainly during loadInteractions landing on start-up long tasksLess and later JavaScript; streamed server rendering; lighter hydration
One script dominatesA specific first- or third-party script, visible in LoAF attributionFix, defer, replace with a facade, or remove
Diagnosing INP by phase: what it usually means and where to look

LCP and CLS: the practical short list

On mobile, LCP fails more often than INP, so it deserves attention too. Google's LCP optimisation guide splits it into four parts: time to first byte, resource load delay, resource load duration and element render delay. As a rough guide, it suggests about 40% of the time for each of the first-byte and download parts and under 10% for each delay. The fixes that matter most: make the LCP image discoverable in the initial HTML, give it fetchpriority set to high, never lazy-load it, serve modern image formats at the right size, cache HTML at the edge where you can, and avoid client-side rendering for above-the-fold content.

CLS is usually the easiest to fix once you know where shifts come from. The CLS guide lists the familiar causes: images and iframes without dimensions, ads and embeds without reserved space, banners injected above content, and web fonts swapping in with different metrics. Set width and height or aspect-ratio on media, reserve space for anything that loads late, insert content below the fold or in response to user action, use fallback fonts with matched metrics, and animate with transform. Making pages eligible for the back/forward cache also removes shifts for returning visitors. Shifts within 500 ms of user input do not count.

Core Web Vitals are part of the page experience that Google says its ranking systems seek to reward, and Google recommends achieving good scores. But its own page experience documentation is unusually direct about the limits: there is no single page experience signal, good Core Web Vitals do not guarantee top rankings, and chasing a perfect score purely for SEO may not be the best use of time.

"Google Search always seeks to show the most relevant content, even if the page experience is sub-par." Google Search Central, page experience documentation

Our reading: treat Core Web Vitals as a user-experience and conversion issue first, with a search benefit at the margin. Moving from poor to good is worth real effort, because poor scores reflect pages that feel broken on phones. Moving from good to perfect rarely is. If a competitor outranks you, their content and relevance are a far more likely explanation than their INP.

A practical order of work

  1. Check the field data. Open Search Console's Core Web Vitals report and PageSpeed Insights for your key templates on mobile. Note which metric fails and where.
  2. Add RUM with attribution. Install the web-vitals attribution build, or configure your RUM product to capture interaction targets, phase timings, load state and LoAF scripts. A week or two of data from real traffic is usually enough to see the patterns.
  3. Rank the slow interactions. Group by page template and interaction target. Fix the few that cause most of the poor sessions, not every warning in Lighthouse.
  4. Reproduce in the lab. Record the interaction in Chrome DevTools with CPU throttling to see exactly which tasks run.
  5. Fix by phase. Use the table above: input delay points to other work on the main thread, processing to your handlers, presentation to rendering.
  6. Guard against regressions. Add Lighthouse or TBT budgets to CI, review every new third-party tag, and watch field INP after each release.
  7. Confirm in the field. Lab gains do not always translate. Wait for RUM, then CrUX's 28-day window, before declaring victory.

Performance is not a one-off project. New features, new tags from marketing and framework upgrades erode it quietly, which is why we treat monitoring and budgets as part of ongoing maintenance and support rather than an occasional audit. For online shops, where filters, search and checkout are interaction-heavy, the e-commerce development guide covers the wider architecture choices that make good INP easier or harder.

When not to spend time on this

If your pages are internal tools used on fast desktops, CrUX may have no data and search ranking is irrelevant; measure responsiveness with RUM if users complain, otherwise spend the effort on features. If your site already passes on mobile, keep monitoring but stop optimising. And if a fix requires a full framework migration, treat it as a modernisation decision with its own business case, not a performance tweak; many large improvements come from removing scripts and simplifying components, without a rewrite.

How Authect approaches web performance

On our front-end development projects, performance is a requirement from the first sprint rather than a clean-up at the end: server rendering by default, client JavaScript only where interaction needs it, media with dimensions and lazy loading below the fold, and third-party scripts loaded deliberately. Every project is led by a senior engineer, and we use AI to speed up delivery while an engineer reviews every line. For existing sites, a software audit starts with field data and RUM to find the interactions that actually hurt users, then fixes them in order of impact. Clients own the code and the monitoring from day one. If your mobile INP or LCP is failing and you want a second opinion, talk to the founders.

For more on how the browser side and server side of a web application divide the work, see our guide to front-end vs back-end development.

Частые вопросы

What is a good INP score?

200 milliseconds or less at the 75th percentile of page visits, measured separately for mobile and desktop. Between 200 and 500 ms needs improvement, and above 500 ms is poor. The score for a visit is its slowest interaction, ignoring rare outliers on pages with many interactions.

Why does Lighthouse not show INP?

INP depends on real user interactions, and a standard Lighthouse run loads the page without clicking anything. Lighthouse reports Total Blocking Time as a lab proxy instead. To measure INP in a lab, record a user flow or an interaction in Chrome DevTools; to know your real score, use CrUX, Search Console or your own real-user monitoring.

Why is my INP good on desktop but poor on mobile?

Phones, especially mid-range Android devices, have much slower CPUs, so the same JavaScript takes several times longer and long tasks become far more common. Testing on a fast laptop hides this. Use CPU throttling in DevTools and look at mobile field data specifically.

How long does it take for INP improvements to show in Search Console?

Search Console uses Chrome UX Report data, which is a 28-day rolling window, and its validation process monitors for 28 days. Expect roughly a month after a fix is live for most users before the report reflects it fully. Your own RUM will show the change within days.

Do Core Web Vitals affect Google rankings?

They are part of the page experience Google says its ranking systems reward, but Google states there is no single page experience signal, good scores do not guarantee top rankings, and relevance comes first. Fix poor scores for your users' sake; do not expect a perfect score to lift rankings on its own.

Does a single-page application hurt INP?

Not by itself, but SPAs tend to ship more JavaScript, render more HTML on the client and re-render larger trees on interaction, all of which raise INP. Server rendering, smaller client components, transitions for non-urgent updates and virtualised lists address most of it. Note that CrUX attributes SPA route changes to the initial page view.

Can third-party scripts really ruin INP?

Yes. They run on the same main thread as your code, so a tag manager or chat widget executing when a user taps a button adds directly to input delay. The Long Animation Frames API, available in Chrome and Edge, attributes slow frames to specific script URLs, which is the clearest way to prove which tag is responsible.

Pranas MickeviciusChief Executive Officer
Опубликовано:
4 ноября 2026 г.
  • Web performance
  • Core Web Vitals
  • INP
  • Frontend
  • SEO

Заметки о разработке раз в месяц

Чему мы учимся, создавая SaaS-платформы, приложения и функции на базе ИИ: коротко, по делу и от основателей, которые сами делают эту работу.

Одно письмо в месяц. Отписаться можно в любой момент. Политика конфиденциальности

Похожие материалы

Больше материалов

Расскажите, что вы создаёте. Основатель ответит в течение одного рабочего дня и сам будет разрабатывать проект вместе с вами.

Мы внесём ваши данные в нашу CRM, чтобы связаться с вами по вашему запросу. Подробнее — в нашей политике конфиденциальности.