WSWhat Scene?

Guide · 9 min read

Core Web Vitals, measured

Core Web Vitals are LCP, INP and CLS, judged on real visitors at the 75th percentile over 28 days. A testing tool measures one simulated visit instead, so it can pass while the ranked number fails. The gap between the two is where most confusion about vitals lives.

The three metrics, and what each one reports

Core Web Vitals are three numbers Google uses as part of how it ranks pages. Largest Contentful Paint asks how long until the biggest visible thing finished loading. Interaction to Next Paint asks how long the screen takes to update after somebody taps or types. Cumulative Layout Shift asks how much the page moved around while it was loading.

MetricGoodNeeds workPoorWhat it is about
LCPunder 2.5s2.5s to 4.0sover 4.0sloading
INPunder 200ms200ms to 500msover 500msresponsiveness
CLSunder 0.10.1 to 0.25over 0.25visual stability
Google's boundaries for a good rating, as of August 2026.

The detail that gets dropped from most write-ups is the word behind every one of those thresholds: percentile. You do not pass by averaging well. You pass when 75% of real visits come in under the boundary, which means the slowest quarter of your visitors decides your rating. A site that is quick for most people and dreadful for the rest fails, and an average would have hidden that.

CLS has no unit. It is a score built from how much of the screen moved multiplied by how far it moved, so 0.1 is not 0.1 of anything you can point at. Treat it as a boundary to stay under rather than a quantity to reason about.

The number you can measure is not the number you are ranked on

There are two kinds of performance data and they answer different questions. Lab data comes from running a test: one machine, one network, one simulated visit, repeatable on demand. Field data comes from actual visitors using actual devices, collected by Chrome and published in the Chrome User Experience Report.

Google ranks on the field data. Specifically, it looks at the 75th percentile of the last 28 days of real visits to your origin. A test tool cannot produce that number, because a test tool has no visitors. It can only produce its own reading and let you infer.

  • Lab data is a diagnosis. It tells you which element is slow and what is blocking it, which is exactly what you need to fix something.
  • Field data is the verdict. It is what Google actually uses, and it includes the visitor on a five year old phone on a bad connection who never appears in your test.
  • A page can pass every lab check and still fail in the field. This is the normal case, not the edge case, because lab conditions are better than real ones almost by definition.

The practical consequence is that a green score proves less than it appears to. It proves the page can be fast on the machine that ran the test. Whether it is fast for the people who visit is a separate question with a separate source of truth, and only one of those two questions affects ranking.

What we measured on our own build

Rather than describe the method, here is the output of it. We measured eight routes at two viewports, sixteen runs in total, against a production build of this site served locally. Every figure below is from that single recorded run on 25 August 2026, and the full artifact including the routes not shown here is in the repository.

Mobile, 390pxDesktop, 1440px
Time to first byte8ms6ms
First Contentful Paint248ms360ms
Largest Contentful Paint1,184ms1,460ms
Cumulative Layout Shift0.0000.000
Worst CLS on any route0.0210.015
Transfer on a cold load467 KB345 KB
Median across eight routes, one run each. Lab measurements over a loopback connection.

All sixteen runs came in under both the LCP and the CLS boundary. That is the least interesting thing in the data, and on its own it would be the kind of result that gets published as a win and teaches nobody anything. Three other things in the same run are worth more.

The first is that on the home page, First Contentful Paint and Largest Contentful Paint are the same number: 452ms and 452ms on mobile, 448ms and 448ms on desktop. The largest element is also the first thing painted, so there is no second wait. On every content page the two separate by roughly a second, with the article pages painting something at around 250ms and not finishing the largest element until about 1,200ms. Same site, same build, a completely different loading shape.

The second is that desktop is slower than mobile here, 1,460ms against 1,184ms at the median, while also transferring less: 345 KB against 467 KB. Weight and latency are not the same lever, and this run is a small demonstration of it. A wider viewport selects a physically larger element as the LCP candidate, and a larger element finishes later even when the total download is smaller.

The third is one we cannot explain from this data, and it is the most useful line in the artifact. Mobile downloads more than desktop, 467 KB against 345 KB, which is the wrong way round for a site serving responsive images. We have not run it down yet. It is recorded as an open question rather than given a plausible-sounding cause, because a guess written confidently is indistinguishable from a finding.

The time to first byte figures above are 6ms and 8ms. Do not read anything into that. It is a loopback connection with no network in the path, so it measures how fast the server renders and nothing about how fast anybody reaches it. It is in the table because leaving it out would have been a quieter way of doing the same thing.

Why there is no INP number on this page

INP measures the delay between a person interacting with the page and the screen updating in response. Every part of that requires a person. A scripted run does not tap anything, so there is no interaction to time, and any INP figure produced by one is a proxy wearing the name of the real metric.

Our own Lighthouse configuration takes this position already. It asserts budgets for LCP, CLS, First Contentful Paint and Speed Index, and it deliberately does not assert INP. It asserts Total Blocking Time at 200ms instead, which is the accepted lab stand-in: it measures how long the main thread was too busy to respond, which is the usual cause of a bad INP without being a measurement of INP.

So the measurement script does not emit one either. Naming the gap is worth more than filling it, and a guide about the difference between measurable and ranked numbers would be a poor place to quietly blur that difference.

INP replaced First Input Delay as a Core Web Vital in March 2024. FID only looked at the first interaction of a visit, which flattered pages that were quick to greet you and slow to use. INP considers interactions across the whole visit, which is why a lot of sites that passed FID comfortably do not pass INP.

What actually moves each metric

Each vital has a small number of causes that account for most real failures. Measuring first matters more than the list, because on any given page one item usually dominates and the rest are noise.

  • LCP: identify which element is actually the LCP candidate before changing anything, because it is often not the one you assume. Then serve it at the size it renders, in a modern format, without lazy loading it. Lazy loading the largest above-the-fold image is a common own goal, since it delays the exact element the metric is timing.
  • LCP, again: the element cannot paint before the server responds and the render-blocking resources finish. If time to first byte is slow, no amount of image work will fix the number.
  • INP: the cause is nearly always JavaScript occupying the main thread when somebody taps. Break long tasks up, defer what is not needed for the first interaction, and be suspicious of third-party scripts, which run on your main thread and are not accountable to you.
  • CLS: reserve space for anything that arrives late. Set explicit width and height on images and video so the browser can hold the gap, give ads and embeds a fixed container, and handle web fonts so the swap does not reflow the text around it.
  • CLS, again: a shift caused by the visitor tapping something does not count against you. Only unexpected movement does, which is why an accordion opening is fine and an image pushing a button down as you reach for it is not.

Page weight sits underneath all three without being a vital itself. It is not measured directly, and a heavy page can still pass, but weight is where the causes live: the large image is an LCP problem, the large script is an INP problem, and the thing that arrives late enough to move the layout is a CLS problem.

How to check your own, and what an empty report means

  1. Open the Core Web Vitals report in Google Search Console. This is field data for your site, grouped by URL pattern, and it is the closest thing to the number you are ranked on.
  2. Run PageSpeed Insights on a specific page. It shows field data at the top when it has any, and lab data underneath. The two sections are different measurements of different things, which is worth knowing before comparing them.
  3. Use Lighthouse or the browser's own performance panel to diagnose. This is where you find out which element is the LCP candidate and what is blocking the main thread.
  4. Check on a real phone on mobile data at least once. It is not rigorous and it is not a percentile, but it catches things that no desktop simulation surfaces.

If the field section is empty, that is a finding rather than a failure. The Chrome User Experience Report only publishes data for an origin once it has enough visits to report without identifying individuals. Below that threshold there is no field data at all, which means no Core Web Vitals assessment exists for the site and nothing is being held against it on that basis.

For a new or low traffic site, that is the ordinary situation, and it reframes the work. There is nothing to fix yet, because nothing is being measured yet. Building the page to be fast before the data arrives is still worth doing. Optimising against a lab score in the meantime, and treating that score as the thing being ranked, is the mistake this whole guide is about.

What this does not cover

  • Our figures are lab measurements, not field data. They describe a headless browser talking to a local server with no network in between, which is the most favourable condition a page will ever see. They say nothing about what a visitor experiences.
  • One run per route per viewport. Our Lighthouse configuration takes the median of three runs because a single run is noisy, so treat a difference of a few tens of milliseconds between two of our rows as no difference at all.
  • No INP figure appears anywhere in this guide, for the reason given in its own section. If you need one, it has to come from field data or from real interactions.
  • The mobile transfer being heavier than desktop is unexplained. We have recorded it and not diagnosed it, and it may turn out to be a defect in our build rather than anything general.
  • We have not queried the CrUX API for our own origin, so we make no claim about whether this site currently has field data. The point about low traffic origins is about how the threshold works, not a statement about our own numbers.
  • The thresholds cited are Google's as of August 2026. They have changed before: INP replaced FID in March 2024. Check the current boundaries rather than trusting a dated page, including this one.
  • Nothing here covers what to do about a third-party script you cannot remove, which is the most common real constraint and deserves its own treatment.

Sources

  • whatscene.in production build, 8 routes at 2 viewports. Headless Chromium with a PerformanceObserver installed before navigation, fresh browser context per route so every load is a cold cache, measured over loopback against a local production build. LCP and CLS from the observer, transfer bytes from the Resource Timing entries. Run: scripts/vitals-evidence.mjs, 2026-08-25, recorded in content/VITALS-EVIDENCE.md.
  • Web Vitals, Google. Retrieved 25 August 2026.
  • Interaction to Next Paint (INP), Google. Retrieved 25 August 2026.
  • Chrome UX Report, Google. Retrieved 25 August 2026.
  • Understanding page experience in Google Search results, Google. Retrieved 25 August 2026.

Revisions

  • 25 August 2026 First published, with measurements from the first recorded run of scripts/vitals-evidence.mjs.

This page is revised in place rather than replaced, so its address does not change.

Next step

Want this built, not just explained?