Turns Out · · 14 min read
Core Web Vitals in 2026: LCP, INP and CLS thresholds — and what actually moves them
LCP, INP and CLS explained with current thresholds, field vs lab data, and the fixes that actually move each Core Web Vital on real sites in 2026.
The ticket usually reads “fix Core Web Vitals”. By the time it reaches us it has been open for a quarter and the Lighthouse score has gone from, say, 61 to 94 without the Search Console report changing color once. Nobody did anything wrong. They optimized the number the tool put in front of them, and that number is not a Core Web Vital.
Core Web Vitals are three field metrics Google collects from real Chrome users: Largest Contentful Paint (how long until the biggest thing above the fold is drawn), Interaction to Next Paint (how long the page takes to respond to a tap or click) and Cumulative Layout Shift (how much the layout jumps during the visit). Three numbers, two tools that disagree, and a ticket that is really three different engineering problems.
What the three Core Web Vitals measure, and the 2026 thresholds
Picture one visit on a timeline. The three metrics sit on it in a fixed order:
- Request sent — DNS, TLS, redirects and server think time run first. This is Time to First Byte (TTFB). It is not one of the three, but nothing paints before the HTML arrives, so it is the floor under LCP.
- The first big paint — LCP marks the moment the largest image, video poster or text block in the viewport finishes rendering. It is measured once per page load and stops updating when the user interacts.
- Every tap, click and key press — INP watches each discrete interaction for the whole visit and reports the slowest one (on busy pages, Chrome ignores one outlier per 50 interactions). Scrolling and hovering do not count.
- Every unexpected movement — CLS groups layout shifts into session windows of at most 5 seconds, with less than 1 second between shifts, and reports the worst window. Shifts within 500 ms of a tap or click are excused.
The thresholds, verified on web.dev at the time of writing, are the ones you remember:
- LCP — good at 2.5 seconds or less, poor above 4 seconds.
- INP — good at 200 milliseconds or less, poor above 500 milliseconds.
- CLS — good at 0.1 or less, poor above 0.25.
Three details matter more than the numbers. Each threshold applies at the 75th percentile of page loads, so a page passes when three visits in four meet the target. Mobile and desktop are scored separately, and most sites fail on mobile first. And a page passes only when all three metrics are good at once.
The thresholds are not arbitrary: Google’s threshold paper required every “good” value to be achievable by at least 10% of origins in Chrome’s field data, and rejected a 1-second LCP target because only 3.5% of phone origins met it. The 2025 Web Almanac, built on July 2025 CrUX data, puts 48% of mobile websites and 56% of desktop websites at good on all three, up from 44% and 55% a year earlier.
Field data vs lab data: why PageSpeed Insights disagrees with itself
Open PageSpeed Insights for any busy page and you get two reports on one screen: field data from the Chrome User Experience Report (CrUX) on top, a single Lighthouse run with the circular score below. They answer different questions, and the stacking is why so many teams optimize the wrong one.
CrUX is what Google Search looks at. It comes from Chrome users who opted into usage statistics and sync, on Android and desktop only; Chrome on iOS, Android WebViews and other Chromium browsers such as Edge are excluded. It is a 28-day rolling window updated daily, so a fix shipped today takes four weeks to fully replace the old data, and a page appears only if it is indexable and gets enough traffic (Google does not publish the minimum). Below that line you see origin-level data or nothing.
Lighthouse is one run, on one emulated device, over one throttled connection, with a cold cache. That makes it reproducible and useful for debugging. It also means a standard run cannot measure INP, because INP needs a human to interact. Lighthouse reports Total Blocking Time instead, a lab proxy for main-thread time blocked by tasks over 50 ms during load. TBT is worth 30% of the Lighthouse performance score, more than LCP (25%) or CLS (25%), and it is not one of the three. A Lighthouse 95 does not say what CrUX will say.
Search Console adds a third layer: its Core Web Vitals report groups URLs that share a template into one row, scored by the group’s worst metric, and falls back to origin-wide figures when a group lacks data. That is how a slow listing template drags a fast blog post into “poor”.
Google is careful about what any of this buys you in rankings. The Search Central documentation, updated in December 2025, says good Core Web Vitals are highly recommended and that page experience, taken together,
“aligns with what our core ranking systems seek to reward.”
Our reading: the ranking effect is real but modest, a tie-breaker rather than a lever. The business reasons to fix these metrics are conversion, crawl budget on large sites, and not losing the people on cheap Android phones. An SEO and AEO program depends on the same fixes, because answer engines read the server HTML with little or no JavaScript, so TTFB and discoverable content matter to them too.
Largest Contentful Paint: four sub-parts and the three fixes that matter
LCP is the metric most sites fail: 62% of mobile websites and 74% of desktop websites had good LCP in the 2025 Almanac. TTFB is the quiet accomplice; only 44% of mobile origins hit the 0.8-second mark web.dev calls good.
The useful way to work on LCP is the four sub-parts web.dev defines, with the share of total LCP time each should take on a healthy page:
- Time to First Byte, about 40% — redirects, DNS, TLS and the server building the HTML. Full-page caching and a CDN edge fix most of it; a chain from
http://tohttps://towww.adds a round trip per hop before anything starts. - Resource load delay, under 10% — the gap between the HTML arriving and the browser starting to fetch the LCP image. It should be near zero. It is not when the image is lazy-loaded, injected by JavaScript or referenced only from CSS.
- Resource load duration, about 40% — the download itself: image size, format and competing high-priority requests.
- Element render delay, under 10% — the time between the image finishing and the pixels appearing, usually a render-blocking stylesheet or synchronous script in the
head.
In the 2024 Almanac’s breakdown of pages with poor LCP, the 75th-percentile TTFB was 2,270 ms and the resource load delay 1,290 ms, before the image had started downloading. Load duration, where most image-compression budgets go, was the smaller problem.
The three fixes, in the order we apply them:
- Make the LCP image discoverable and tell the browser it matters. A real
imgwithsrcorsrcsetin the HTML, never behinddata-src, never withloading="lazy", plusfetchpriority="high". In the 2025 Almanac, 16 to 17% of pages still lazy-load their LCP image and only 17.3% of mobile pages set the priority hint on it. If the hero comes from CSS, preload it. - Cut TTFB with caching before touching the image. A cached HTML response from a CDN edge removes server think time and most of the geography. On Craft CMS that is a static cache plugin plus a CDN; on Next.js it is static generation or ISR for anything that does not change per user. The redirect chain goes in the same ticket.
- Serve the right pixels. Responsive
srcset, AVIF or WebP, a width that matches the slot. On Craft CMS, pre-generate named image transforms rather than letting the first visitor trigger them. Withnext/image, thepriorityprop handles the preload and the hint, but only if the hero is anext/imageand not a CSS background.
<img src="/img/hero-1200.avif"
srcset="/img/hero-800.avif 800w, /img/hero-1200.avif 1200w, /img/hero-1600.avif 1600w"
sizes="(min-width: 1200px) 1200px, 100vw"
width="1200" height="675"
fetchpriority="high" alt="…">Two inflaters nobody expects: a cookie banner that is the largest element for the first second, and a web font with font-display: block holding back the hero headline.
Interaction to Next Paint: the metric mobile sites fail
INP replaced First Input Delay in 2024, and it is a harder metric. FID measured only the delay before the first handler ran; INP measures the whole interaction, every time, and takes the worst: input delay (the main thread was busy when the tap landed), processing duration (your handlers ran) and presentation delay (the browser laid out and painted the result).
That gap, from the 2025 Almanac, is the whole story. Desktop machines hide long tasks that a mid-range Android phone cannot. The same report found the median mobile page’s lab TBT rose 58% in a year to 1,916 ms while field INP slowly improved: pages ship more JavaScript and rely on faster phones to absorb it.
The fixes, by sub-part:
- Input delay: break up long tasks. Any task over 50 ms blocks the thread. Hydration, the step where a React or Next.js page attaches its JavaScript to the server-rendered HTML, is the usual culprit; so are tag managers firing six vendors at once. Yield between chunks of work with
scheduler.yield()where supported (check current browser support) orsetTimeout, and move analytics initialization out of the first second. - Processing duration: do less in the handler. Update the UI first, defer the rest. Avoid reading layout right after writing it in the same task; that forced layout shows up as a red “Layout” triangle in the DevTools Performance panel.
- Presentation delay: give the browser less to paint. Smaller DOM,
content-visibility: autoon long off-screen sections, and never render a few thousand rows in one go, because the browser cannot yield until the render finishes.
The honest caveat: the biggest INP win we see on content sites is removing scripts, not optimizing them. Each chat widget, consent manager, heatmap and session recorder costs main-thread time on every page, and most were added for a campaign that ended. Where the JavaScript is the product, a front-end team that understands hydration cost is the fix; where it is a tag, deletion is.
Cumulative Layout Shift: size everything, then check the bfcache
CLS is the metric most sites pass, 81% on mobile and 72% on desktop in the 2025 Almanac, and the most embarrassing to fail, because it means the “Buy” button moved under the user’s finger. A shift’s score is the share of the viewport that moved multiplied by how far it moved, so a full-width banner is expensive and a sidebar wobble is not.
The causes have not changed in five years:
- Unsized media. 62% of mobile pages still have at least one image without
widthandheight, a median of two per page. Set the attributes, or use CSSaspect-ratiofor anything whose size is known only as a ratio: embeds, ad slots, video posters. - Late content above existing content. Cookie banners that push rather than overlay, promo bars injected by a script, “related posts” that shove the footer. Reserve the height with
min-heightor render the slot server-side, empty. - Fonts. A fallback swapping to a web font with different metrics reflows every paragraph;
size-adjuston the fallback stops it. - Animations on layout properties. Animating
top,left,marginorheightcounts toward CLS unless it happens within 500 ms of an interaction; animatingtransformdoes not. - Back/forward cache misses. A page restored from bfcache has no load and no shifts. A
Cache-Control: no-storeheader on the HTML still keeps it out, and the rules keep changing, so run the bfcache tester under Application in DevTools.
.embed, .ad-slot, .video-poster {
aspect-ratio: 16 / 9;
width: 100%;
}Diagnose Core Web Vitals in 10 minutes
This is the routine we run before quoting any Core Web Vitals optimization work. Field data first; the lab only to find the cause of what the field already said.
- Minutes 1–2: PageSpeed Insights, field section only. Read the CrUX block for mobile, then desktop. Note which metric fails and whether the figures are for this URL or the whole origin.
- Minutes 3–4: Search Console, Core Web Vitals report. Mobile report, sorted by poor. One template usually explains most of the red.
- Minute 5: TTFB from your desk. Run the command below against the failing template with a cold cache. Anything over 800 ms is a server or caching problem for whoever owns hosting and infrastructure.
- Minutes 6–7: find the LCP element. Record a DevTools Performance trace with mobile CPU throttling, click the LCP marker and read the sub-part breakdown.
- Minutes 8–9: reproduce a slow interaction. Keep recording and tap the menu, open a filter, type in the search box, during load as well as after. The Interactions track shows the three sub-parts for each one.
- Minute 10: layout shifts. Turn on the Layout Shift Regions rendering option, reload, scroll to the bottom. Every blue flash is a shift; the Layout Shifts track lists the elements.
curl -o /dev/null -s -w "dns %{time_namelookup}s tls %{time_appconnect}s ttfb %{time_starttransfer}s total %{time_total}s\n" \
-H "Cache-Control: no-cache" https://example.com/Monitoring, and what we would not bother with
Monitoring is the part most teams skip, and the reason the ticket reopens a year later. The minimum is the Search Console report checked monthly for the top templates; the better setup is real-user monitoring with the open-source web-vitals library, which attributes every INP value to an element and a script.
Watch one change in how the metrics are measured rather than what they measure. Single-page apps currently get one LCP, INP and CLS per hard load, however many “pages” the user visits by JavaScript. Chrome’s soft navigations API, which would score each route change as its own page view, entered its final origin trial in Chrome 147 in April 2026, with the decision on whether it feeds CrUX and Search Console still to come. If your site is a React or Next.js app with client-side routing, verify the status at the time of reading.
What we advise against, having watched each burn a quarter:
- Chasing a Lighthouse 100. The last ten points come from TBT and Speed Index tuning that users never feel and CrUX never records.
- Lazy-loading everything. Correct below the fold, wrong on the hero. “Add
loading="lazy"to all images” is the most common cause of poor LCP we find on sites that recently “optimized”. - A plugin that promises to fix Core Web Vitals. On WordPress, Shopify and Craft CMS alike these mostly delay scripts, which improves lab TBT and often worsens INP when the deferred work lands on the first tap.
- Rewriting the site as a single-page app for speed. It moves the cost from server time to hydration time and gives INP a bigger problem than LCP had.
Questions readers ask
Are Core Web Vitals a ranking factor?
Yes, as part of the page experience signals, and Google describes the effect as aligning with what its core ranking systems reward rather than as a lever. In our experience the gains from fixing them show up in conversion before they show up in rankings.
Why does Lighthouse pass but Search Console says poor?
They measure different things. Lighthouse is one lab run with no interactions, so it cannot report INP and uses TBT instead; Search Console is 28 days of real Chrome users at the 75th percentile, mostly on phones slower than the lab’s emulation. Trust Search Console for what to fix and Lighthouse for finding the cause.
Did the Core Web Vitals thresholds change in 2026?
No. LCP 2.5 seconds, INP 200 milliseconds and CLS 0.1 are unchanged on web.dev at the time of writing, and Google commits to changing a stable metric at most once a year. What is changing is measurement, with soft navigations in a final origin trial.
How long until a fix shows up in the report?
CrUX is a 28-day rolling window, so the report improves gradually and reflects the fix fully after four weeks, provided the page keeps enough traffic to be reported. Search Console’s “Start tracking” runs on the same clock, so start it the day you ship.
If you want the ten-minute routine run on your site, our free website audit covers the three metrics with lab tests and real-user CrUX data, ranks every finding by severity, and says plainly when the answer is “leave it alone”.