Site speed

Core Web Vitals in depth

Core Web Vitals is three numbers measuring three completely different things: LCP for how fast the largest element of the page appears, INP for how fast the page answers a click or a tap, and CLS for how much the layout shifts on its own. Google judges all three not from your test run but from the 75th percentile of real visitors, segmented across mobile and desktop.

  • Lesson 3 of 10
  • Intermediate
  • Free, no signup

The number that decides whether you pass

It is not your test score. It is the 75th percentile of real visitors, segmented across mobile and desktop, and all three metrics have to meet the target together.

0 100
75%the percentile the assessment runs on
  • LCPthe largest element of the page, 2.5 seconds or less
  • INPresponse to click and tap, 200 milliseconds or less
  • CLSunwanted layout movement, 0.1 or less

The needle rests on the edge of the target zone and claims nothing about where you are. Only your own field data knows that, and a low traffic site may have none at all.

Last checked: Facts and tool names in this lesson are re-checked against their sources on this date.

What each of the three numbers actually measures

Core Web Vitals is three metrics, not one score. Their names arrive together, which makes many people treat them as three views of the same thing. They are not. Each captures a different moment of the visit, and each usually breaks for a different reason.

LCP, Largest Contentful Paint, is the moment the largest content element inside the viewport is rendered. Usually that is a big image or a block of text. Google documentation says sites should strive to have Largest Contentful Paint of 2.5 seconds or less. This number answers the question "did I see anything".

INP, Interaction to Next Paint, is the gap between what the user does and the moment the browser paints the next frame. Google writes that a page should have an INP of 200 milliseconds or less, and that anything above 500 milliseconds counts as poor. This number answers "when I tapped, did something happen".

This is exactly where language models and old articles both get it wrong. INP is the successor metric to FID, and Google own page says so. The difference is not small: FID measured only the input delay of the first interaction on a page, while INP observes every interaction for as long as the user is there, from the input delay through the event handlers up to the frame the browser finally paints. If you see the number 100 milliseconds quoted somewhere, it belongs to a metric that is no longer a Core Web Vital.

CLS, Cumulative Layout Shift, has no unit of time at all. It is a unitless number saying how much the page content moved without the user asking for it. Google writes that sites should strive to have a CLS score of 0.1 or less. This number answers "did the thing I was about to tap stay where it was".

Three different questions, three different answers. A page that is excellent on one can be terrible on another, and that is not rare: a light text page with a great LCP and one heavy chat script has a bad INP and a fine LCP. The simpler introduction to these three lives in the primer we wrote for them, and this lesson does not start there, it continues from there.

Three black gauges with red, green and blue needles, a glass sheet slightly shifted on the third

Why your number is not the number Google sees

Beginners get this distinction wrong and so do language models, and most fruitless arguments about speed start right here. There are two kinds of data, and the names are worth learning.

Lab data comes from a simulated run: a hypothetical device, a hypothetical network, one page load. It is repeatable, it is available right now, and it is excellent for finding causes. It is nobody real experience.

Field data is collected from real visitors. The Chrome User Experience Report is exactly that: anonymised real user measurement for each of the three metrics. This is the data Google judges you on.

And here is the number that changes everything. Google writes that to ensure you are hitting the recommended target for most of your users, a good threshold to measure is the 75th percentile of page loads, segmented across mobile and desktop devices. So the slowest quarter of your users decides whether you pass, and a tool assessing Core Web Vitals should consider a page passing only if it meets the target at the 75th percentile on all three metrics.

The consequence for an Iranian site is direct: a test on your laptop over a good connection most likely shows the best case, while your 75th percentile comes from a phone on a network that is not steady. The gap between those two numbers is not something to fill in by guessing.

The second problem is mentioned less often: you may have no field data at all. Google publishes the eligibility rules for that dataset, and one of them is that the page or origin has to be sufficiently popular, meaning it needs a minimum number of visitors. Google does not publish what that minimum is. So if the field section for your site is empty, nothing is broken; that is the normal state of a low traffic site, and the only way forward is to accept it and treat lab data as a clue rather than a verdict.

Two numbers, both correct, never the same

Lab data

  • one simulated run on a hypothetical device and network
  • available right now, even for a brand new site
  • repeatable, so it is good for finding the cause
  • it is nobody real experience

Field data

  • collected from your own real visitors
  • this is what Google judges, at the 75th percentile
  • mobile and desktop are counted separately
  • for a low traffic site it may not exist at all

Neither column beats the other; they do different jobs. You find the cause in one and you get the verdict from the other.

When LCP is bad, where did the time go

"LCP is bad" is a symptom, not a diagnosis. Google itself breaks LCP into four parts, and that breakdown is what turns the work from guessing into reading.

The first part is time to first byte: from the request to the moment the server sends the first byte of the response. The second is resource load delay: the time between that first byte and the moment the browser even starts loading the LCP resource. The third is resource load duration, the download of that image or font itself. The fourth is element render delay: from the end of the download until the element is fully rendered.

Google also publishes a rough distribution for those four: time to first byte about 40% of LCP, resource load delay under 10%, resource load duration about 40%, and element render delay under 10%. Google immediately adds that these breakdowns are guidelines rather than strict rules, and explicitly recommends not converting the percentages into absolute numbers.

Even with that warning, the split makes one thing clear that the local market often states backwards: roughly eighty percent of a typical page LCP sits in two parts that are not about your plugins at all. One is server response time and the other is downloading a file. If someone prescribes plugin removal for your bad LCP without first looking at when the first byte arrives, they are starting in the middle. The relationship between hosting and these numbers is opened separately in our piece on how hosting moves Core Web Vitals.

LCP is four parts, and two of them eat most of it

approximate share of each part of LCP, per Google documentation
  1. about 40%
  2. under 10%
  3. about 40%
  4. under 10%
  • Time to first byte about 40%
  • Resource load delay under 10%
  • Resource load duration about 40%
  • Element render delay under 10%

Google itself writes that this breakdown is a guideline rather than a strict rule, and recommends not converting these percentages into seconds. Your site may look completely different, and only your own measurement answers that.

Where INP and CLS usually break

INP breaks because of JavaScript, almost always. The user taps, and before the browser can paint the next frame it has to wait for whatever is running at that moment to finish. Anything that holds the main thread creates that wait: a counter script, a chat widget, a slider, an ad script, or theme code doing heavy work at the moment of the click. Something that rarely shows up in reports: INP watches the entire lifetime of the page, not just the first seconds, so a script that loads three seconds after the page opens can ruin it too.

CLS breaks in two families. First, things that were given no room: an image, video or iframe with no declared dimensions that pushes the rest of the page down when it arrives. Second, things that arrive late: a banner, a notification bar, content injected above the fold by JavaScript, or a font that relays out the text after it was already visible.

And now the rule almost no tutorial writes down, without which you will read CLS wrong: layout shifts that occur within 500 milliseconds of user input get flagged, so they can be excluded from the calculation. That means when you tap the menu button yourself and the menu opens, that shift is not added to your CLS. This is deliberate: the browser separates "the page jumped under my hand" from "I caused that". Anyone who does not know this reports their own accordion and menu as a CLS problem and spends the time in the wrong place.

One more boundary, because without it these three numbers become idols: a good CLS means the page does not jump under the user hand, not that the design is good. A site with a CLS of zero and copy nobody understands is still a bad site.

Not every shift is charged to you

CLS sheetwhat gets counted

Added to your CLS

  • an image with no declared dimensions that pushes text down when it arrives
  • a banner or notice bar that lands above the fold late
  • a font that relays out the text after it was already visible
  • content JavaScript injects into the middle of the page

Not counted

  • a menu opening after the user tapped the button
  • an FAQ accordion opening on the user own click
  • any shift within 500 milliseconds of user input

The lower column makes no sense without the 500 millisecond rule. Not knowing it is how people report their own menu as a CLS problem.

What these three numbers do not tell you

Three green metrics means your page does not misbehave under the user hand. That is all it means. It does not say your content answers the question, it does not say your price is reasonable, and it does not say the page is indexed. Google itself writes on the page experience documentation that a good score does not guarantee a top position.

There are also two things these numbers simply do not see. One is the speed of what happens after the page load: Core Web Vitals is focused on the visit, and although INP watches the whole lifetime of the page, it still says nothing about how long your form takes to submit. The other is the experience of users who, for whatever reason, are not in that dataset.

So the right order of work is this: first check whether the page you want to make fast matters to anyone at all, then go to these three numbers. The next lesson in this track shows which tools produce them and how to read the report; the full lesson list is on this track page.

The fast path, with AI

The usual way to ask about Core Web Vitals is to put the question straight to a chatbot. For this topic that is the worst possible move, and the next block says why: the thresholds have changed and the text of the internet is still full of the old numbers. The fast path makes one small change that changes everything: instead of asking the model memory, hand the Google documentation pages themselves to a document grounded tool and ask from inside the source. The answer then comes from Google text, and you can trace every sentence of it back.

  1. Give a document grounded tool the Google documentation pages listed in the sources at the bottom of this lesson: the Web Vitals page and the dedicated LCP, INP and CLS pages. If your tool accepts URLs, the addresses are enough; if not, save the page text and upload it.
  2. Put your own three numbers next to it, from field data and not from a test run. If you have no field data, write exactly that and ask the model to carry the gap into its answer rather than drawing a field conclusion from a lab number.
  3. Give it the prompt below. Its important rule is that every sentence has to come back to a source you uploaded yourself, and anything absent from those sources has to be declared unknown out loud. This does not need an expensive model; what you want is accurate quotation rather than judgment, so a fast cheap model of the Gemini Flash class is enough. The current pick in each class is kept in our AI reference.
  4. Test the answer with one simple probe: ask the model what the good threshold for INP is and where that comes from. If it says anything other than 200 milliseconds, or cannot point the sentence back to a source, the sources were not loaded properly and the rest of the answer is not trustworthy either.

Copy-ready recipe

Answer only from the sources I have uploaded. Mark any claim that is not in those sources with the words "not in the sources" and do not guess.

My numbers (field data, 75th percentile):
LCP = {number or "I have no field data"}
INP = {number or "I have no field data"}
CLS = {number or "I have no field data"}
Device: {mobile | desktop | both}

Write five things:
1. For each of the three metrics, quote the "good" threshold from the source and say which page it came from.
2. Say which of my three numbers fails, and by how far from the threshold.
3. For each failing metric, list the likely causes the source itself names, and add no cause of your own.
4. If one of my numbers was "I have no field data", do not write that the metric is fine; write that no judgment is possible about it and what would be needed to make one.
5. At the end, write which sentences of your answer you could not trace back to a source.

Rules: never write a threshold from memory. Where the source carries a qualifier such as "guidelines, not strict rules", carry that qualifier into your answer. Do not convert any percentage into seconds. If you notice you hold older information about the FID metric, set it aside and quote only the source.

Before you trust the output: This makes the answer traceable, not necessarily correct. Two things stay yours. First, the source you upload has to be today page, not a copy you saved three years ago; the INP page was last updated in September 2025, which is itself proof that these pages move. Second, the causes the model pulls out of the source are a list of possibilities, not a diagnosis of your site; the diagnosis comes from measuring the page, and that is exactly what the next lesson in this track is about.

AI in this kind of work

Our position here is stricter than in other lessons: for Core Web Vitals numbers, never put a language model to work without a source in front of it. The reason is not taste, it is history. The middle metric of this family was replaced, the thresholds moved, and the text these models trained on repeated the old numbers for years. On this topic a model hands you the consensus of the internet, and here that consensus is stale. The same model with a source in front of it is a good tool.

Tools that actually help

  • NotebookLM This is the right tool for this job, because it builds the answer from a source you supplied and shows the citation. Load the web.dev pages and ask the threshold question from inside the source. It runs on a Google account, and Google own help says it works in the same places the Gemini app works; Iran is not on the supported-countries list for the Gemini apps.
  • Gemini Useful when you have a long field report and want large tables read. For the threshold question, still do not lean on it without a source. Google own page says the Gemini web app runs in over 230 countries and territories, and Iran is not on that list.
  • ChatGPT Same rule: it works well with an uploaded source and repeats the old numbers without one. We make no claim about access from Iran, because the OpenAI supported-countries page, like the rest of that domain, returns 403 to this server, and we do not write a claim with nothing behind it.

Where it backfires

The main risk here is one specific thing, and it has a name: the model gives you a threshold that is no longer correct, in the same confident tone it would use for the correct one. FID was the middle metric of this family for years, and Google own page says INP is its successor. The tutorial text of the internet is still full of the number 100 milliseconds and the name FID, and a model answering without a source quotes exactly that text. In practice that means you can spend a month optimising something that is no longer counted. Anthropic own documentation calls this pattern, a model stating with confidence something it cannot back, a hallucination. The second risk is quieter: the model takes your lab number and issues a verdict about field status. Our position is simple: an uploaded source, or silence. For these three numbers, an answer that cannot be traced to the documentation page is not an answer.

Sources: web.dev: Interaction to Next Paint, the successor to FID Anthropic: reduce hallucinations Google: where Gemini Apps are available

Where this advice stops

This lesson does not measure the numbers for you and makes no page faster; it only makes you read the numbers correctly. It has three other boundaries. First, every number here comes from Google documentation as it stands today, and that documentation is alive; the verified date sits at the top of this page, and if a long time has passed, open the source links yourself. Second, none of these three metrics says anything about whether your site makes money, and we claim no such thing. Third, our experience comes from small and medium Iranian businesses; at the scale of large international retailers, where every ten thousandth of a second is measured in money, the balance between these three numbers is different and we have no first-hand experience at that scale to sell you.

From our own work

All three metrics can be targeted without buying a single plugin, if you are willing to pay something for it. We measured the front page of this site on 8 September 2026, and all three decisions are visible in the page source. For LCP, the largest element of our front page is deliberately text and not an image: the whole document carries zero img tags, because everything on this site that looks like an infographic is drawn with HTML and CSS. For INP, the main stylesheet has exactly one animation left, the waiting spinner, and no transition at all; the head carries zero scripts and all seven scripts on the page sit at the end of the document, the first of them starting after 96 percent of it. For CLS, our own written rule is that any image placed inside body copy must carry explicit width and height. Now the price we actually paid: these decisions constrain how the site can look, and stripping animation takes something away from a page. We accepted it because we know the trade, and the point of the lesson is that you should be able to judge that same trade yourself rather than take it from us. You can check every one of these right now by viewing the source of the front page.

Real follow-up questions

Does a green score in a test tool mean my Core Web Vitals pass?

Not necessarily. That score comes from a lab run, and Google judges on the 75th percentile of your real visitors, separately for mobile and desktop. If you have field data, that is the only place with the real answer; if you do not, a green score only says nothing was broken in that one run.

Why is the field data section of my report empty?

Most likely because your page or origin has not reached the minimum number of visitors Google requires for inclusion in the dataset. Google publishes the condition but not the number. This is not a fault and no setting fixes it; until then, treat lab data as a clue.

Is INP just FID with a new name?

No. Google own page says INP is the successor metric to FID, but what it measures is different: FID only saw the input delay of the first interaction on a page, while INP observes all interactions for the whole visit and counts up to the next paint. So neither the old threshold nor the old number is of any use now.