↑↓ to move ↵ to open Esc to close Browse all tools

Website guide

Core Web Vitals Explained: LCP, INP and CLS

Core Web Vitals are three numbers Google uses to describe how a page feels to real visitors: how fast the main content appears, how quickly the page reacts to a tap, and how much it jumps around while loading. Here is what each metric measures, the thresholds, how the 75th percentile rule works, where to find your numbers, and what to fix first.

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.

MetricWhat it measuresGoodPoor
Largest Contentful Paint (LCP)Loading: when the largest image, text block or video in the viewport is rendered2.5 s or lessOver 4 s
Interaction to Next Paint (INP)Responsiveness: the delay from a click, tap or key press to the next frame on screen200 ms or lessOver 500 ms
Cumulative Layout Shift (CLS)Visual stability: how much visible content jumps without the user asking0.1 or lessOver 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:

PartWhat happensRecommended share
Time to first byteFrom the start of navigation until the first byte of the HTML arrivesAbout 40%
Resource load delayFrom the first byte until the browser starts loading the LCP imageUnder 10%
Resource load durationDownloading the LCP imageAbout 40%
Element render delayFrom the image arriving until it is on screenUnder 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:

PartMeasuredShareGuideline
Time to first byte0.6 s15%about 40%
Resource load delay1.8 s45%under 10%
Resource load duration1.2 s30%about 40%
Element render delay0.4 s10%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:

Layout shift score
impact fraction × distance fraction

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.

ToolDataWhat you get
PageSpeed InsightsField and labThe 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 reportFieldYour pages in groups of similar URLs, each group rated by its worst metric, over the last 28 days
Chrome UX Report (CrUX)FieldThe dataset behind both: Chrome users on desktop and Android who opted in, for pages that are public and popular enough
web-vitals JavaScript libraryFieldAll three metrics from your own visitors, sent to your own analytics
Chrome DevToolsLabLCP, INP and CLS while you use the page yourself
LighthouseLabLCP 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

  1. Look at mobile and desktop separately. They are assessed apart, and one can pass while the other fails.
  2. Fix the metric that is poor, then the one that needs improvement. One poor metric fails the whole page group in Search Console.
  3. For LCP, find the LCP element and split its time into the four parts. Attack the part furthest above its share.
  4. For CLS, add image dimensions and reserve ad and banner space. These can be small template changes that fix many pages at once.
  5. For INP, click through the page with DevTools recording, find the slowest interaction and the long task behind it.
  6. 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