Skip to main content

Core Web Vitals 2026: how to actually pass INP, LCP and CLS

A perfect Lighthouse score and a failing Search Console report are not a contradiction — they are two different tests. This is how to read the field data that actually counts, diagnose each of the three metrics from first principles, and fix the causes rather than the symptoms.

By SBPO Consulting

Lab scores and field data are not the same test

The most common performance conversation starts with a screenshot of a green Lighthouse score and a screenshot of a failing Search Console report, and the question of which one is lying.

Neither is. They measure different things, and the difference is the single most useful thing to understand about this subject.

Lab data is a simulated load: one page, one device profile, one throttled network, one location, no cache, no logged-in state, no consent banner interaction. It is a debugging instrument. It is repeatable, which makes it excellent for comparing two builds, and unrepresentative, which makes it a poor verdict.

Field data comes from the Chrome User Experience Report — real Chrome users on real devices and connections. PageSpeed Insights reports it “over the previous 28-day collection period”, and the Search Console Core Web Vitals report uses the same source. This is what Google’s systems see.

Three consequences follow immediately. Lighthouse cannot measure INP at all, because there is nobody there to click anything — a perfect lab score tells you nothing about the metric most sites fail. Your users’ devices are, in aggregate, slower than the machine you tested from. And a script that only loads after consent is granted does not exist in most lab runs but exists for most real users.

So use lab tools to find and verify causes, and field data to decide whether you have a problem at all. Reversing that is how teams spend a quarter optimising something that was never failing.

The 75th percentile rule and the 28-day window

Two mechanics in the measurement explain most of the confusion.

The threshold is the 75th percentile, not the average. Google assesses each metric at “the 75th percentile of page loads, segmented across mobile and desktop devices”. You are being judged on the slower quarter of your visits. A site with an excellent median and an occasional half-second stall on a filter control will fail, and the median will keep telling you everything is fine. Always look at the distribution, never the mean.

Metric Good Needs improvement Poor
Largest Contentful Paint 2.5 seconds or less 2.5 to 4.0 seconds Over 4.0 seconds
Interaction to Next Paint 200 milliseconds or less 200 to 500 milliseconds Over 500 milliseconds
Cumulative Layout Shift 0.1 or less 0.1 to 0.25 Over 0.25

The window is 28 days and it rolls. A fix shipped today spends the next month competing with the old experience inside the same average. Expect movement within a week or two and a settled number after roughly a month. The Search Console report runs validation as a 28-day monitoring session for the same reason.

Two further quirks of the CrUX methodology are worth knowing before you argue with the data. A page needs to be publicly discoverable and sufficiently popular to get its own URL-level entry — pages below the visitor threshold have no individual data, which is why Search Console groups similar URLs together and why many sites only ever see origin-level numbers. And when only origin-level data exists, one badly performing template can drag the entire domain’s assessment down, which is both unfair and useful: it means fixing your worst template improves the number reported for everything.

LCP: find the element that paints last, then find out why

Largest Contentful Paint is the render time of the largest image, text block or video visible in the viewport. Candidates include img elements, image elements inside svg, video elements via their poster or first frame, elements with a CSS url() background image, and block-level elements containing text.

Two mistakes dominate. The first is optimising the wrong element — teams compress the hero image when the LCP element is actually a heading blocked by a webfont, or a background image on a section nobody thought of as content. Identify it first, in Chrome DevTools or via the web-vitals library, on the templates that matter.

The second is treating LCP as an image problem when it is usually a discovery problem. Google’s optimisation guidance breaks LCP into four parts with a suggested distribution: Time to First Byte around 40%, resource load delay under 10%, resource load duration around 40%, and element render delay under 10%. The two sub-10% parts are the ones that go wrong. Resource load delay is the gap between the page starting to load and the browser starting to fetch the LCP resource — pure waste, and it is usually caused by the image being introduced by JavaScript, by CSS, or by a lazy-loading library, so the browser’s preload scanner never sees it in the initial HTML.

The fixes, in the order they usually pay off:

  1. Make the LCP resource discoverable in the initial HTML. A plain img in the server-rendered markup is found by the preload scanner immediately. An image injected by a client-side component is not. If it must be referenced from CSS, add a link rel="preload" for it.
  2. Mark it as important. Setting fetchpriority="high" on the likely LCP image tells the browser to promote it above the other images it discovered at the same time.
  3. Never lazy-load the LCP image. This is the most common self-inflicted regression on sites that added lazy loading globally. Lazy-load everything below the fold and nothing above it.
  4. Cut render-blocking work. Inline the small amount of CSS needed for the first viewport, defer the rest, and stop non-critical JavaScript from blocking the parser.
  5. Reduce TTFB. Cache at the edge, avoid redirect chains on entry URLs, and check whether the server is doing work per request that could be done at build time.
  6. Then compress the image. Modern formats, correct dimensions for the breakpoint, and a sensible quality setting. This is the step everyone does first and it is rarely where the seconds are.

If your LCP element is text, the webfont is usually the culprit: preload the font file, use font-display: swap or optional, and set a metrics-compatible fallback so the swap does not also cost you CLS.

INP: the vital most sites fail, and why

Interaction to Next Paint replaced First Input Delay because FID measured only the delay before a handler started running, which flattered almost everybody. INP measures the whole thing: from a click, tap or key press to the next frame the user actually sees. It ignores scrolling and hovering.

That total splits into three phases, and the reason INP is hard is that most teams only ever look at the middle one.

  • Input delay — the time before any callback runs, because the main thread was busy with something else. Often a third-party script, a hydration pass, or an analytics beacon.
  • Processing duration — the time your event handlers take to execute. The part everyone profiles.
  • Presentation delay — the time between the callbacks finishing and the frame appearing. Driven by how much the browser has to re-style, lay out and paint, which is driven by DOM size.

Fixing INP therefore means three different investigations. If input delay dominates, the problem is what else is running — usually startup scripts, and usually not yours. If processing duration dominates, the problem is your handler doing too much in one go. If presentation delay dominates, the problem is a large or expensive DOM, and the lever is content-visibility on off-screen sections, plus simply rendering fewer nodes.

A practical detail that catches people: INP is worst on the interactions users perform while the page is still loading. A visitor who taps the menu two seconds in is competing with every script still initialising. Measure interactions during load, not on an idle page you have been staring at for a minute.

Breaking up long tasks

The main thread does one thing at a time. Any task over 50 milliseconds blocks everything else, including your user’s tap. The fix is not to make the work smaller — often you cannot — but to break it into chunks and let the browser handle input between them.

The classic approach is to split work across tasks with setTimeout, which reliably yields but sends the continuation to the back of the queue. The newer and better tool is scheduler.yield(), which returns a promise and, per MDN, places the continuation at the front of its priority queue rather than the back — so you yield to genuinely urgent work without losing your place to every other pending task. It is not yet Baseline across browsers, so feature-detect it and fall back rather than assuming it exists.

The pattern that fixes most real INP problems is simpler than either API, though:

  1. Do the visible thing first. Show the state change — the menu opening, the button entering its loading state — then yield, then do the expensive work. The user perceives the response, which is what the metric is measuring.
  2. Defer everything that is not rendering-critical. Analytics calls, saving to storage, spell-checking, recalculating derived data. None of it has to happen before the next frame.
  3. Debounce input handlers, particularly on input and scroll.
  4. Avoid layout thrashing. Reading a layout property after writing a style forces a synchronous reflow. Batch reads, then writes.
  5. Be careful with client-side rendering. Streamed HTML gives the browser natural yield points; building a large chunk of DOM in JavaScript does not, and it can block the frame you are trying to present.

CLS: reserve the space before the layout moves

Cumulative Layout Shift measures unexpected movement. Each shift scores impact fraction multiplied by distance fraction — how much of the viewport moved, times how far. The reported CLS is the worst session window, where a window is a burst of shifts less than one second apart, capped at five seconds total.

Two implications follow. A single large shift can fail a page on its own, and a slow drip of small shifts across a long page can accumulate into a failure that no individual shift explains.

The causes are well catalogued in Google’s CLS guidance, and so are the fixes:

Cause Fix
Images without dimensions Always set width and height, or an aspect-ratio in CSS, so space is reserved before the file arrives
Ads, embeds and iframes Reserve the slot with min-height or aspect-ratio; place unpredictable content below the fold where possible
Dynamically injected banners and notices Render them in the initial HTML, or reserve their space, or trigger them from a user interaction
Web fonts Preload the font, use font-display: optional or a metrics-matched fallback so the swap does not resize the text block
Content awaiting a network response Render a placeholder of the correct size; a change made within 500 milliseconds of a user interaction is not counted against you

The cookie banner deserves its own sentence. A consent notice injected by a third-party script after the page has painted, pushing everything down, is one of the most reliable CLS failures on the web — and it is entirely avoidable by reserving the space or overlaying rather than inserting.

The other frequent offender is the sticky header that changes height on scroll, and the “back to top” bar that appears mid-page. Both are design decisions with a measurable cost, which is why performance budgets belong in the web design phase rather than in QA.

On most commercial sites, the majority of blocking JavaScript was not written by the people responsible for the site’s performance. It arrives through a tag manager, added over years by marketing, sales and analytics teams, each addition individually reasonable.

Third-party scripts hurt all three metrics: they delay LCP by competing for bandwidth and blocking the parser, they inflate INP by occupying the main thread during exactly the window when users first interact, and they cause CLS when they inject content.

A workable approach, in order:

  1. Measure before arguing. Chrome DevTools can block individual requests, and web.dev’s third-party guidance recommends exactly that: load the page with and without a script and compare. This turns “we need that tag” into a conversation about a number.
  2. Audit the container. Most tag manager containers hold tags for tools nobody uses any more. Removing them is free.
  3. Load correctly. Use async or defer for anything not on the critical rendering path, and preconnect for the origins you genuinely need early — sparingly, because each hint costs a connection.
  4. Use facades for heavy embeds. A static thumbnail that loads the real video player, chat widget or map on click removes a large amount of work from the initial load for the majority of visitors who never use it.
  5. Move what you can server-side. Server-side tagging shifts some of the work off the user’s device, though it is not automatically a performance win and it brings its own complexity — our note on consent mode and server-side tracking sets out the trade-offs.

The consent banner is a special case worth its own attention: it runs early by necessity, it usually blocks other scripts, and it frequently causes layout shift. Whatever else you defer, this is the one script whose performance you should measure directly.

Architecture choices that make vitals easy or impossible

Some decisions make good vitals nearly automatic, and some make them a permanent maintenance burden. It is worth being honest that this is a trade-off rather than a hierarchy — the architectures that are hardest to keep fast are often the right choice for genuinely application-like interfaces.

Server-rendered HTML with minimal JavaScript — static site generators, traditional server-rendered stacks, and islands architectures such as Astro — makes LCP and INP straightforward, because the content arrives ready to paint and there is very little main-thread work competing with the user’s first interaction. The cost is that highly interactive interfaces need deliberate work to build.

Client-side rendered single-page applications put the initial paint behind a JavaScript download, parse, execute and render cycle, and hydration adds a burst of main-thread work at precisely the moment users start interacting. This is a real cost, and it buys something real: fast subsequent navigation, and a much better development model for stateful, application-shaped interfaces. If you are building a genuine web application, the trade is often correct — it just has to be made knowingly, with the mitigations budgeted.

Modern hybrid approaches — server components, partial hydration, streaming, selective islands — exist precisely to take most of that cost back, and they are the reasonable default for content-heavy sites that also need interactivity.

The practical guidance is not “use framework X”. It is: match the architecture to what the page actually is. A marketing site rendered entirely on the client is paying an application’s performance cost for a brochure’s requirements. An interactive dashboard rendered as static HTML is paying a maintenance cost for nothing. Most organisations have both, and the mistake is picking one architecture for the whole estate. Getting that decision right at the start of a build is the performance work with the largest payoff, which is why it belongs in the web development specification rather than a later optimisation phase.

A measurement loop that survives the next core update

One-off optimisation projects decay. Within a year, someone adds a hero video, a new tag goes into the container, and a component starts rendering a thousand rows. A loop is what keeps the gains.

  1. Collect your own field data. The web-vitals JavaScript library reports LCP, INP and CLS from your real users, with attribution — which element, which script, which interaction. CrUX tells you that you have a problem; your own real-user monitoring tells you where.
  2. Watch Search Console by group. The Core Web Vitals report clusters similar pages, which usually maps to templates. A failing group is a failing template, and templates are fixable once.
  3. Set a performance budget in CI. A budget on JavaScript bytes and on the LCP of key templates, enforced on every pull request, prevents regression far more reliably than periodic audits. Something has to fail loudly when a new dependency adds weight.
  4. Test on representative hardware. A mid-range Android phone on a throttled connection, not the laptop the site was built on.
  5. Re-check after every significant release, and especially after a redesign or replatform — the performance benchmark is one of the things a migration should protect, as our redesign migration guide sets out.
  6. Include third parties in the review. Whoever owns the tag manager should be part of the loop, not a source of surprises.

Do Core Web Vitals actually affect rankings?

This is where the industry genuinely disagrees, so it is worth quoting Google directly rather than paraphrasing. On page experience, Google says: “There is no single signal. Our core ranking systems look at a variety of signals that align with overall page experience.” It also states that “Core Web Vitals are used by our ranking systems”, while noting that good scores in the Search Console report do not guarantee good positions.

Both halves are true and they are frequently quoted separately by people arguing opposite cases. The defensible reading is that vitals are a real but modest input, most likely to matter as a tie-breaker between pages of comparable relevance, and incapable of rescuing a page that does not answer the query. Anyone promising rankings from a performance project is overselling; anyone telling you it does not matter at all is contradicting Google’s own documentation.

The stronger argument is commercial and does not depend on the ranking question. Pages that paint late, respond slowly or move under a user’s thumb lose conversions — and that is true whether or not any search system ever notices. Fix the metrics because the experience is better, and treat the search effect as a secondary benefit rather than the business case. If you also need the search side of the work handled properly, that sits with technical SEO, and on transactional sites the interaction between page speed and revenue is worth measuring specifically within e-commerce development rather than assumed.

Questions

Common questions

What is a good INP score?

Google defines a good INP as 200 milliseconds or less, measured at the 75th percentile of page views. Between 200 and 500 milliseconds is "needs improvement", and above 500 milliseconds is poor. The percentile matters more than people expect: you are not being judged on your average interaction but on the slower quarter of them, which is where the slow devices, the cold caches and the users with fifteen tabs open live. A site whose median interaction is 90 milliseconds can still fail comfortably if a menu, a filter or a cookie banner occasionally takes half a second to respond.

Why does my PageSpeed score not match Search Console?

Because they are measuring different things. The Lighthouse performance score at the bottom of a PageSpeed Insights report is a lab test: one simulated load, on one simulated device, on one simulated network, from one location. The Core Web Vitals section at the top, and everything in Search Console, is field data from the Chrome User Experience Report — real Chrome users, on their real devices and connections, over the previous 28-day collection period. Lighthouse also cannot measure INP at all, because there is no real user to interact with the page. A 100 score with failing field data usually means real users are on slower hardware than the simulation, or that a script only loads once consent is granted, or that logged-in pages behave differently from the anonymous page you tested.

How long until an improvement shows up in field data?

PageSpeed Insights reports field data over the previous 28-day collection period, so a fix deployed today competes with 27 days of the old experience before the window is clean. Expect partial movement within a week or two and a settled figure after roughly a month, assuming traffic is steady. The Search Console Core Web Vitals report works the same way and runs its validation as a 28-day monitoring session. The practical consequence is that you should not judge a fix by field data alone. Confirm the mechanism improved in lab and real-user monitoring first, then wait for the field to confirm it at scale.

Do Core Web Vitals affect rankings directly?

Google states that "Core Web Vitals are used by our ranking systems" while also saying that "there is no single signal" for page experience, and that good scores on the Search Console report do not guarantee good rankings. The reasonable interpretation is that vitals are a real but modest input, most likely to matter between pages of otherwise comparable relevance and quality. They will not lift a page that does not answer the query. The stronger commercial argument is the direct one: slow, unstable pages lose conversions, and that effect does not depend on how any ranking system weights it.

Can a WordPress site pass Core Web Vitals?

Yes, and plenty do. The platform is rarely the deciding factor; the plugin count, the theme and the page builder usually are. The pattern that fails is a heavy multipurpose theme plus a visual builder plus fifteen plugins, each loading its own CSS and JavaScript on every page whether or not the page uses it. The pattern that passes is a lean theme, server-side caching, an image pipeline that emits modern formats with explicit dimensions, and a deliberate audit of what each plugin loads and where. If you have inherited the first pattern, the cheapest meaningful win is usually removing render-blocking assets from pages that do not need them, before anyone considers a rebuild.

Related services

If you would rather not do this yourself

Web development

Fast, secure, maintainable websites built in modern frameworks and CMS platforms — engineered so performance and accessibility survive the first year of edits.

Web design

Research-led website design that turns a visitor into an enquiry — accessible, fast, and grounded in what your buyers are actually trying to do.

Technical SEO

Crawl and indexation audits, rendering and performance work, structured data and migration planning — the layer that decides whether your content is eligible to compete at all.

Keep reading

Next step

Tell us what you are trying to build.

Send us the problem, the constraint and the deadline. You will get a considered reply from someone who would actually do the work — not a templated proposal.