The three metrics and their thresholds
Google's web.dev defines three Core Web Vitals, each with a good and a poor limit. Values between the two need improvement.
| Metric | What it measures | Good | Poor |
|---|---|---|---|
| Largest Contentful Paint (LCP) | Loading: when the largest image, text block or video in the viewport is rendered | 2.5 s or less | Over 4 s |
| Interaction to Next Paint (INP) | Responsiveness: the delay from a click, tap or key press to the next frame on screen | 200 ms or less | Over 500 ms |
| Cumulative Layout Shift (CLS) | Visual stability: how much visible content jumps without the user asking | 0.1 or less | Over 0.25 |
The set is not fixed forever. web.dev says stable Core Web Vitals change at most once a year and changes are announced in advance. The last change came on March 12, 2024, when Interaction to Next Paint (INP) replaced First Input Delay (FID). FID only measured how long the first interaction waited before its handler started; INP covers every interaction and the whole time until the screen updates.
The 75th percentile rule
Every visit gets its own values. A visitor on a fast laptop sees a different page from one on an old phone in a train. To turn thousands of visits into one number, web.dev uses the 75th percentile, split into mobile and desktop. A metric is good when at least 75% of page views reach the good threshold. A page passes when all three metrics are good at the 75th percentile.
Why 75 and not the average or the median? web.dev explains that the value should make sure a majority of visits reach the target while not being overly moved by outliers. Three in four visits is that balance.
In practice: if 80 of your last 100 mobile visits saw LCP at or below 2.5 seconds, the 75th percentile is below 2.5 seconds and mobile LCP is good. If only 70 did, it is not, even though most visitors were fine. That is why making the slowest visits faster moves the number more than making fast visits faster still.
LCP: when the main content shows
Largest Contentful Paint is the time from the start of navigation until the largest image, text block or video visible in the viewport is rendered. Candidates are img elements, image elements inside an SVG, the poster or first frame of a video, elements with a CSS background image loaded through url(), and block-level elements that contain text. Chrome ignores elements with zero opacity, elements that cover the whole viewport and low-entropy placeholder images. The browser stops reporting new candidates once the user taps, scrolls or presses a key.
The four parts of LCP
web.dev splits LCP into four parts that add up to the total, and gives rough shares for a well-optimized page:
| Part | What happens | Recommended share |
|---|---|---|
| Time to first byte | From the start of navigation until the first byte of the HTML arrives | About 40% |
| Resource load delay | From the first byte until the browser starts loading the LCP image | Under 10% |
| Resource load duration | Downloading the LCP image | About 40% |
| Element render delay | From the image arriving until it is on screen | Under 10% |
A worked example. A product page has an LCP of 4.0 seconds on mobile, which is poor. Splitting it shows where the time goes:
| Part | Measured | Share | Guideline |
|---|---|---|---|
| Time to first byte | 0.6 s | 15% | about 40% |
| Resource load delay | 1.8 s | 45% | under 10% |
| Resource load duration | 1.2 s | 30% | about 40% |
| Element render delay | 0.4 s | 10% | under 10% |
The load delay takes 45% of the time instead of under 10%. The browser found the hero image late, for example because it is lazy-loaded, set as a background in a stylesheet, or inserted by JavaScript. Fix that first: it is the biggest slice, and it does not need a smaller image or a faster server.
How to improve LCP
- Put the LCP image in the HTML. If it only appears through CSS or JavaScript, preload it with a link rel="preload" tag.
- Never lazy-load the LCP image. web.dev says this always adds load delay. Lazy-load images further down instead.
- Add fetchpriority="high" to the likely LCP image, and to no more than one or two images.
- Make the image smaller. Serve it at the size it is displayed, in a modern format, compressed. The image resizer, the image compressor, the WebP converter and JPG to AVIF do this in your browser.
- Cut the time to first byte with fewer redirects and a CDN that serves cacheable pages from the edge. The website speed test splits the first byte into DNS, connection, TLS and server wait, and the HTTP header checker lists every redirect on the way.
- Remove render-blocking files from the head: shrink or inline small stylesheets, and avoid synchronous scripts. The CSS and JS minifier trims the files that remain.
INP: how fast the page reacts
Interaction to Next Paint watches every mouse click, tap and key press during a visit and reports the longest one, ignoring outliers: on a page with many interactions, one of the highest is dropped for every 50. Hovering, scrolling and zooming are not counted. A visit without any click, tap or key press has no INP value.
Each interaction has three parts. Input delay is the wait before the event handler can start, usually because the main thread is busy with something else. Processing duration is the time the handlers run. Presentation delay is the time from the end of the handlers until the browser paints the next frame. A slow INP means one of the three is long, and the fix depends on which.
How to improve INP
- Break up long tasks. web.dev defines a long task as anything over 50 milliseconds on the main thread. Split the work and yield back to the browser between pieces, with scheduler.yield() where it is supported and a setTimeout fallback where it is not.
- Update the screen first, then do the rest. Inside a click handler, make the visible change, then defer analytics, saving and validation to a later task.
- Load less script. Parsing and running large scripts during load creates long tasks that delay the first taps.
- Avoid layout thrashing. Reading a size right after changing a style forces the browser to lay out the page again in the same task. Batch the writes, then read.
- Keep the DOM small and use content-visibility for long sections below the fold, so each update has less to render.
CLS: how much the page jumps
Cumulative Layout Shift adds up unexpected movements of visible content. Each shift gets a score:
The impact fraction is the area the moving elements cover before and after the shift together, as a share of the viewport. The distance fraction is the furthest any of them moved, divided by the larger side of the viewport. Shifts that follow each other with less than 1 second between them, within at most 5 seconds, form a session window, and CLS is the window with the highest total. Shifts within 500 milliseconds of a click, tap or key press do not count, because the user expects the page to change.
A worked example on a 400 × 800 pixel phone viewport. A 400 × 400 pixel block of text starts 200 pixels from the top. A cookie banner loads above it and pushes it down 100 pixels. Before and after, the block covers the band from 200 to 700 pixels, so the impact fraction is 200,000 ÷ 320,000 = 0.625. The distance fraction is 100 ÷ 800 = 0.125. The shift scores 0.625 × 0.125 = 0.078, under the 0.1 limit on its own. If an ad slot then pushes the same block down another 100 pixels half a second later, both shifts land in one window and CLS becomes about 0.16, which needs improvement.
How to improve CLS
- Give every image and video width and height attributes, or a CSS aspect-ratio, so the browser reserves the space before the file arrives. The website speed test lists images without them.
- Reserve space for ads, embeds and late content with min-height or aspect-ratio, and keep the space even when no ad fills it.
- Do not insert content above content the visitor is already reading. Put banners in reserved space or overlay them.
- Animate with transform, not with top or left, which move the layout.
- Tame web fonts: preload the important ones, pick a close fallback, and use font-display: optional or size-adjust so swapping fonts does not reflow the text.
- Keep pages eligible for the back/forward cache, so a visitor going back gets the finished page without a second round of shifts.
How to measure them
There are two kinds of data, and they answer different questions. Field data comes from real visitors and is what the assessment uses. Lab data comes from one simulated load and is what you debug with.
| Tool | Data | What you get |
|---|---|---|
| PageSpeed Insights | Field and lab | The Core Web Vitals assessment from CrUX over the previous 28 days, for the URL or, without enough data, the whole origin; below it a Lighthouse lab test with a 0 to 100 score |
| Search Console, Core Web Vitals report | Field | Your pages in groups of similar URLs, each group rated by its worst metric, over the last 28 days |
| Chrome UX Report (CrUX) | Field | The dataset behind both: Chrome users on desktop and Android who opted in, for pages that are public and popular enough |
| web-vitals JavaScript library | Field | All three metrics from your own visitors, sent to your own analytics |
| Chrome DevTools | Lab | LCP, INP and CLS while you use the page yourself |
| Lighthouse | Lab | LCP and CLS, but not INP, since nobody interacts; Total Blocking Time serves as the stand-in |
Reading PageSpeed Insights
The top of the report is the assessment. With enough data for all three metrics, the page passes when LCP, INP and CLS are all good at the 75th percentile. If there is not enough INP data, LCP and CLS decide. The Lighthouse score further down is a different thing: 90 to 100 is good, 50 to 89 needs improvement, 0 to 49 is poor, and it reflects one simulated load on a mid-tier phone over a mobile network. A green score next to a failed assessment means the lab test was kinder than your real visitors' devices and networks.
Why your fix does not show up yet
Field data is a 28-day window. After you deploy a fix, the old visits leave the window day by day, so PageSpeed Insights and Search Console move gradually. Search Console's validation tracks the issue for 28 days and counts it as fixed only if no URL shows it during that time. Check the lab numbers right after deploying, and the field numbers a month later.
The website speed test is a lab test of the network side: it measures time to first byte, page weight, requests, render-blocking files, compression, caching and image dimensions from a server, without running a browser. It does not report Core Web Vitals, but each of those numbers feeds into LCP or CLS, and it sorts its fixes by how much they would gain.
What to fix first
- Look at mobile and desktop separately. They are assessed apart, and one can pass while the other fails.
- Fix the metric that is poor, then the one that needs improvement. One poor metric fails the whole page group in Search Console.
- For LCP, find the LCP element and split its time into the four parts. Attack the part furthest above its share.
- For CLS, add image dimensions and reserve ad and banner space. These can be small template changes that fix many pages at once.
- For INP, click through the page with DevTools recording, find the slowest interaction and the long task behind it.
- Verify in the lab now, in the field in a month.
Frequently asked questions
What are the three Core Web Vitals?
Largest Contentful Paint (LCP) for loading, Interaction to Next Paint (INP) for responsiveness and Cumulative Layout Shift (CLS) for visual stability. Google's web.dev sets the good thresholds at 2.5 seconds or less for LCP, 200 milliseconds or less for INP and 0.1 or less for CLS, measured at the 75th percentile of page loads, separately for mobile and desktop.
When did INP replace FID?
On March 12, 2024. INP became a stable Core Web Vital that day and First Input Delay was retired. FID only measured the input delay of the first interaction on a page; INP looks at every click, tap and key press during the visit and includes the time to run the event handlers and paint the next frame.
Why does PageSpeed Insights show a good score but a failed assessment?
The two come from different data. The score from 0 to 100 is a Lighthouse lab test of one simulated load. The Core Web Vitals assessment at the top comes from CrUX, real Chrome users over the previous 28 days. A page can load fast in the lab and still be slow for real visitors on older phones or slower networks, and Lighthouse cannot measure INP at all because no one interacts with the page.
My site shows no field data. What now?
CrUX only includes pages and origins that are publicly discoverable and have enough visitors, and it does not disclose the exact threshold. Without field data, use lab tools: Lighthouse and Chrome DevTools for LCP and CLS, DevTools for INP while you click through the page yourself, and Total Blocking Time as a lab stand-in for INP. To measure your own visitors, add the web-vitals JavaScript library to the page.
Do Core Web Vitals affect Google rankings?
Google says it highly recommends achieving good Core Web Vitals for success with Search and that they align with what its core ranking systems seek to reward. Its documentation does not say how much they count. Treat them as part of how good a page is for visitors, which is what the metrics measure in the first place.
Sources
- web.dev: Web Vitals (the three Core Web Vitals, good thresholds, 75th percentile segmented by mobile and desktop, lifecycle, field and lab tools, TBT as a lab proxy for INP)
- web.dev: Defining the Core Web Vitals metrics thresholds (good and poor limits, why the 75th percentile)
- web.dev blog: Interaction to Next Paint becomes a Core Web Vital on March 12, 2024
- web.dev: Largest Contentful Paint (LCP)
- web.dev: Interaction to Next Paint (INP)
- web.dev: Cumulative Layout Shift (CLS), including the layout shift score formula
- web.dev: Optimize Largest Contentful Paint (the four subparts and their recommended shares)
- web.dev: Optimize Interaction to Next Paint
- web.dev: Optimize long tasks (a long task is any task over 50 milliseconds)
- web.dev: Optimize Cumulative Layout Shift
- Google for Developers: About PageSpeed Insights (field data from CrUX over 28 days, lab data from Lighthouse, how the assessment passes)
- Chrome for Developers: CrUX methodology (which Chrome users and which pages are included)
- Search Console Help: Core Web Vitals report (URL groups, status by the worst metric, 28-day validation)
- Google Search Central: Understanding Core Web Vitals and Google search results