Core Web Vitals: How to Measure and Fix LCP, INP and CLS
What LCP, INP and CLS measure, the thresholds you need at the 75th percentile, why PageSpeed Insights and Search Console disagree, and a fix playbook for each metric based on Google's own guidance, with a worked example.
Searvia · 10/24/2026 · 16 min read
In short: Core Web Vitals are three metrics Google uses to describe real-user experience: Largest Contentful Paint (LCP, loading, good at 2.5 s or less), Interaction to Next Paint (INP, responsiveness, good at 200 ms or less) and Cumulative Layout Shift (CLS, visual stability, good at 0.1 or less). Each is judged at the 75th percentile of real Chrome visits over 28 days, separately for mobile and desktop. Google says they are used by its ranking systems, but relevance comes first. To fix them, break each metric into its parts and fix the largest part first.
Most Core Web Vitals advice is a list of fifty tips. That is why teams spend a sprint on "performance" and see their numbers barely move. The metrics are more structured than that: each one can be split into a few measurable parts, and usually one part is responsible for most of the problem.
This guide covers what the three metrics measure, the thresholds as of October 2026, which data source to trust, what Google actually says about rankings, and a diagnosis-first playbook for each metric, based on Google's own documentation on web.dev.
What Core Web Vitals measure
Per web.dev's Web Vitals overview, the current, stable set has three metrics:
| Metric | Measures | Good | Needs improvement | Poor |
|---|---|---|---|---|
| Largest Contentful Paint (LCP) | Loading: when the main content appears | ≤ 2.5 s | 2.5 to 4 s | > 4 s |
| Interaction to Next Paint (INP) | Responsiveness: how fast the page reacts to input | ≤ 200 ms | 200 to 500 ms | > 500 ms |
| Cumulative Layout Shift (CLS) | Visual stability: how much content jumps around | ≤ 0.1 | 0.1 to 0.25 | > 0.25 |
The thresholds match the table in About PageSpeed Insights.
The 75th percentile rule
Google does not judge a page by its average or by a single test. Web.dev says a good threshold to measure is "the 75th percentile of page loads, segmented across mobile and desktop devices." In plain terms: at least three out of four real visits must meet the "good" threshold. To pass, a page needs a good result at the 75th percentile on all three metrics.
This has two consequences people often miss:
- Mobile and desktop are separate. A page can be good on desktop and poor on mobile. Mobile is usually the harder one, because phones have slower CPUs and networks.
- Your slow visitors decide the result. If a quarter of your visitors use old Android phones on weak connections, their experience is your score. Testing on a new laptop over office Wi-Fi tells you little.
INP replaced FID in 2024
Interaction to Next Paint replaced First Input Delay (FID) as a Core Web Vital on March 12, 2024. FID only measured the delay before the browser started handling the first interaction. INP covers clicks, taps and key presses throughout the whole visit, and the full time until the next frame is painted. Many sites that passed FID easily fail INP, because the slow part was always the work after the first input, which FID never counted. If you still see FID in an old report or plugin, ignore it.
Web.dev also notes that stable Core Web Vitals "won't change more than once per year," and new candidate metrics stay in a pending stage for at least six months first, so you get notice before the rules change.
Field data vs lab data
There are two kinds of performance data, and confusing them is the most common reason teams fix the wrong thing.
| Field data | Lab data | |
|---|---|---|
| Source | Real Chrome users (Chrome User Experience Report, CrUX) | A simulated page load (Lighthouse, DevTools) |
| Period | Rolling 28 days | One test, right now |
| Measures INP? | Yes | No (Total Blocking Time as a proxy) |
| Used by Google Search? | This is what the Core Web Vitals assessment uses | No |
| Best for | Knowing whether you have a problem | Finding why, and testing a fix before release |
A few details from Google's documentation:
- CrUX is a 28-day rolling average, updated daily, according to the CrUX API documentation. It can be queried for a whole origin or a single URL, and filtered by phone, desktop or tablet.
- PageSpeed Insights shows both. Its field section uses the previous 28 days of CrUX data. If a URL has too few visits, it falls back to data for the whole origin; if the origin is too small, there is no field data at all (About PageSpeed Insights). The lab section and the 0 to 100 score come from Lighthouse.
- Lighthouse cannot measure INP. Web.dev states that tools that load pages "in a simulated environment without a user cannot measure INP," and suggests Total Blocking Time (TBT) as a lab proxy.
- Search Console's Core Web Vitals report groups pages with similar experiences and gives each group the status of its slowest metric for that device type. It uses CrUX data from the last 28 days (Core Web Vitals report help).
The practical rule: field data decides whether you have a problem, lab data helps you find the cause. A Lighthouse score of 98 with poor field LCP means your real users have a worse experience than the simulation, often because of slow devices, ads, personalization or third-party scripts the lab test does not trigger.
How much Core Web Vitals matter for rankings
Google's page experience documentation is clear on both sides:
- "Core Web Vitals are used by our ranking systems," and Google recommends achieving good Core Web Vitals "for success with Search."
- "There is no single signal" for page experience; the core ranking systems look at a variety of signals.
- "Google Search always seeks to show the most relevant content, even if the page experience is sub-par."
- Good results in Search Console or third-party tools do not guarantee that your pages will rank at the top.
- "Trying to get a perfect score just for SEO reasons may not be the best use of your time."
Our reading: Core Web Vitals will not lift an irrelevant page above a relevant one, but they can matter between pages of similar quality, and they matter directly for users. A product page that takes five seconds to show its photo, or a "Buy" button that freezes for half a second, loses customers regardless of rank. Aim for "good" on all three, then stop chasing points and go back to content.
Step 1: Find out which metric fails, and where
Before changing code:
- Open Search Console's Core Web Vitals report, mobile first. Note which metric fails and which URL groups are affected (product pages, blog posts, the homepage).
- Pick one representative URL per failing group and run it in PageSpeed Insights. Check whether the field data is for that URL or for the origin.
- Fix one template at a time. Core Web Vitals problems are almost always template problems: every product page shares the same image component, the same scripts and the same layout.
Our free Core Web Vitals checker gives a fast first read without an account: it pulls the 75th percentile LCP, INP and CLS for phone visitors from CrUX (for the page you enter when Chrome has enough data for it, otherwise for your whole origin), and measures server response time, HTML size, compression, render-blocking scripts in the page head and image formats on that page, your homepage by default.
Step 2: Fix LCP by its four subparts
LCP is the time until the largest image or text block in the viewport is rendered. Eligible elements include <img>, <video>, elements with a CSS url() background image and block-level text (LCP on web.dev). On most product and landing pages it is the hero image.
Optimize LCP splits LCP into four parts that add up to the total:
| Subpart | What it is | Rough target share |
|---|---|---|
| Time to First Byte (TTFB) | Until the first byte of HTML arrives | ~40% |
| Resource load delay | From TTFB until the browser starts loading the LCP image | < 10% |
| Resource load duration | Downloading the LCP image | ~40% |
| Element render delay | From download finished until the element is painted | < 10% |
Web.dev calls these proportions "guidelines, not strict rules," but they are very useful for diagnosis. Chrome DevTools' Performance panel shows the breakdown for a recorded load. Whichever part is far over its share is where you start.
High TTFB
TTFB includes redirects, connection setup and server processing. Web.dev's TTFB guide suggests 0.8 seconds or less as a rough target, while noting TTFB is not a Core Web Vital itself.
- Serve HTML from a CDN and cache it at the edge, even briefly. The most effective ways to improve Core Web Vitals names a CDN as the best way to cut TTFB.
- Remove redirect chains, including those from ad and shortened links.
- Watch for unique URL parameters (from analytics or campaigns) that make every request a cache miss.
- Profile slow database queries and server-side rendering on the page template.
High resource load delay
This is often the largest subpart and usually the cheapest to fix. The browser could have started the image download earlier but did not know about it.
- Put the LCP image in the initial HTML as a normal
<img src>orsrcset. Images inserted by JavaScript, or usingdata-srcfor a lazy-loading library, are discovered late. - Never lazy-load the LCP image. Remove
loading="lazy"from the hero image; web.dev says plainly, "never lazy-load your LCP image." - Add
fetchpriority="high"to the LCP image, and to no more than one or two images. - If the image is a CSS background, preload it with
<link rel="preload">and a high fetch priority, or switch to an<img>. - Serve critical images from the same origin as the HTML where possible, to reuse the connection.
High resource load duration
- Serve the image at the size it is displayed, with
srcsetandsizes, so phones do not download a desktop image. - Use modern formats such as AVIF or WebP, and compress properly.
- Use an image CDN that resizes and converts automatically.
- Reduce other high-priority downloads competing for bandwidth at the same time.
High element render delay
The image has arrived, but something stops the browser from painting it:
- Render-blocking CSS: reduce it, defer non-critical styles, inline only very small critical CSS.
- Synchronous scripts in the
<head>: addasyncordefer. - Client-side rendering: if the page content appears only after a JavaScript framework runs, prefer server-side rendering or prerendering.
- A/B testing or personalization scripts that hide the page until they decide which variant to show.
- Long JavaScript tasks running at the moment the image is ready.
If LCP is a text block rather than an image, resource load delay and duration are zero, and the problem is TTFB, render-blocking resources or web fonts.
Step 3: Fix INP by its three phases
INP records clicks, taps and key presses during the whole visit (not scrolling or hovering) and reports the slowest interaction, ignoring one outlier for every 50 interactions (INP on web.dev). Each interaction has three phases:
| Phase | What it is | Typical cause when it is slow |
|---|---|---|
| Input delay | Waiting before the event handler can start | Other JavaScript is busy on the main thread |
| Processing duration | Running your event handlers | Too much work in the click handler |
| Presentation delay | From handlers done until the next frame is painted | Large DOM, heavy layout and rendering |
The underlying problem is nearly always long tasks: any task that takes longer than 50 milliseconds on the main thread. While a long task runs, the browser cannot respond to the user.
Reduce input delay
- Load less JavaScript during startup; script evaluation creates long tasks exactly when users first try to tap.
- Audit your tag manager. Web.dev notes that "older tags with unused code can be removed." Chat widgets, heatmaps, A/B testing and ad scripts often run heavy work on the main thread.
- Use Chrome's Coverage tool and code splitting to stop shipping code the page does not use.
Reduce processing duration
- Do less in the event handler. Update what the user needs to see first, then defer the rest (analytics calls, saving state, recalculating recommendations).
- Yield to the main thread between chunks of work.
await scheduler.yield()continues the remaining work in a new, prioritized task. It is not supported in every browser, so web.dev suggests falling back tosetTimeoutwrapped in a Promise (Optimize long tasks). - Avoid layout thrashing: reading layout values (such as
offsetHeight) right after changing styles in the same task forces the browser to calculate layout synchronously. Batch reads and writes.
Reduce presentation delay
- Keep the DOM small. Optimize INP explains that rendering work grows with DOM size.
- Use
content-visibilityto skip rendering off-screen sections such as long reviews or footers. - Avoid rendering large chunks of HTML in JavaScript in response to a click; render only what is needed.
To find the slow interaction, look at real-user data first (which pages fail), then reproduce in Chrome DevTools: record a Performance trace while clicking the suspect element on a throttled CPU, and look for long tasks after the click.
Step 4: Fix CLS cause by cause
CLS adds up unexpected layout shifts. Each shift scores the share of the viewport that moved times how far it moved, shifts are grouped into windows of up to five seconds, and CLS is the worst window (CLS on web.dev). Shifts within 500 ms of a click, tap or key press are excluded, because the user expected them. Scrolling does not count as input, so content that shifts while someone scrolls still counts.
Per Optimize CLS, the usual causes and fixes:
| Cause | Fix |
|---|---|
| Images and videos without dimensions | Always set width and height attributes, or CSS aspect-ratio |
| Ads, embeds and iframes | Reserve space with min-height or aspect-ratio; keep a placeholder if no ad loads |
| Content injected late (banners, review widgets, "related products") | Reserve space, place it lower on the page, or load it on user action |
| Web fonts swapping in | Preload key fonts, use font-display: optional, or tune the fallback font with size-adjust |
Animations of layout properties (top, left, height) | Animate transform instead |
| Pages not restored from the back/forward cache | Make pages bfcache-eligible |
Two notes from experience:
- Collapsing space shifts too. Web.dev warns that removing reserved space "can cause just as much CLS as inserting content." If an ad slot stays empty, keep the placeholder.
- Cookie banners and promo bars are frequent culprits. Overlay them on top of the content instead of pushing the page down.
Do not forget the back/forward cache
When users press Back, a page restored from the bfcache appears instantly, with no new loading shifts. Web.dev calls bfcache eligibility a highly effective technique for keeping CLS low. The two most common blockers, per web.dev's bfcache guide: unload event listeners (use pagehide instead) and the Cache-Control: no-store header on pages that do not contain sensitive data. Chrome DevTools has a test under Application › Back/forward cache.
A worked example (hypothetical numbers)
The following is a hypothetical example, not real data. Fernwood Home, an invented online furniture store, has a failing Core Web Vitals assessment on mobile for its product page template. The 75th percentile field values:
| Metric | Before | Status |
|---|---|---|
| LCP | 4.6 s | Poor |
| INP | 340 ms | Needs improvement |
| CLS | 0.21 | Needs improvement |
LCP: 4.6 s
A DevTools trace on a throttled phone profile shows the LCP element is the main product photo. The breakdown:
| Subpart | Before | Share | Problem |
|---|---|---|---|
| TTFB | 1.3 s | 28% | HTML not cached; every campaign link has unique parameters |
| Resource load delay | 1.6 s | 35% | Gallery script inserts the photo; loading="lazy" on all images |
| Resource load duration | 1.2 s | 26% | 2,400-pixel JPEG sent to every phone |
| Element render delay | 0.5 s | 11% | Synchronous A/B testing script in the head |
Resource load delay is more than three times its target share, so it goes first. The fixes: render the first photo as a plain <img> in the server HTML, remove loading="lazy" from it, add fetchpriority="high", serve AVIF and WebP at phone sizes through srcset, cache the HTML at the CDN while ignoring tracking parameters in the cache key, and load the A/B script with defer.
Lab result after the release: TTFB 0.7 s, load delay 0.2 s, load duration 0.6 s, render delay 0.3 s, for an LCP of 1.8 s.
INP: 340 ms
Field data points to the product page; reproducing in DevTools, the slow interaction is the "Add to cart" button. The trace shows about 90 ms of input delay (a chat widget and two tracking tags running at the same moment), 190 ms of processing (the handler re-renders the whole cart drawer and sends three analytics calls synchronously) and 60 ms of presentation delay.
The fixes: load the chat widget only after the first user interaction, show the cart drawer update first, then yield before analytics and recommendation updates. Lab measurement on the same throttled profile: about 150 ms.
CLS: 0.21
Three causes: a review stars widget inserted above the price after load, a web font swap that rewraps the product title, and thumbnail images without dimensions. The fixes: reserve the review widget's height, preload the title font and adjust the fallback with size-adjust, add width and height to every thumbnail. Lab CLS: 0.04.
Reading the result
The lab numbers confirm the fixes work. The field numbers, which decide the assessment, move as new visits replace old ones in the 28-day window. Fernwood should expect a gradual change over about four weeks, then click Start tracking in Search Console's report to begin validation, which also runs for 28 days. If the field LCP lands at, say, 2.3 s rather than 1.8 s, that is normal: real phones and networks are slower than any lab profile.
Common mistakes
- Chasing the Lighthouse score. The 0 to 100 score is a lab summary. Google's assessment uses field data at the 75th percentile.
- Testing only on desktop. Mobile is assessed separately and usually fails first.
- Lazy-loading everything. Lazy-loading below-the-fold images is good; lazy-loading the hero image is one of the most common causes of poor LCP.
- Fixing the homepage only. Most traffic often lands on product, category or article templates. Fix the templates with the most failing URLs.
- Adding one more script. Every tag, widget and test script competes for the main thread. Remove one for each one you add.
- Expecting instant results. Field data needs about 28 days to fully reflect a release.
- Ignoring mobile basics. A page without a viewport tag or with oversized images is slow on phones before any optimization. The free mobile-friendly test checks those basics.
A one-hour starting checklist
- Run your domain through the free Core Web Vitals checker for real-user LCP, INP and CLS on phones, plus server response time, compression and blocking scripts.
- Open Search Console's Core Web Vitals report for mobile and list the failing URL groups.
- For each failing group, run one URL through PageSpeed Insights and note which metric fails in the field.
- For LCP, record a DevTools trace and write down the four subparts. Fix the largest one first.
- For INP, find the slow interaction and the long tasks after it.
- For CLS, check images without dimensions, late-injected content and fonts.
- Ship, confirm in the lab, then check the field data after two and four weeks.
Core Web Vitals are one part of technical health. Our technical SEO audit guide puts them in context with crawling, indexing, redirects and structured data.
How Searvia helps with Core Web Vitals
The free Core Web Vitals checker needs no account and gives you the real-user picture for your site in under a minute. Inside Searvia, the Page speed tab of a website project runs PageSpeed Insights on your most visited pages every week and shows both lab scores and real Chrome user data for LCP, INP and CLS from the last 28 days. Fixes are ordered by the time they save, and Write a fix plan for my files with AI turns the top items into step-by-step changes for your stack (3 credits). Connect Search Console to see clicks and positions next to speed, so you can tell whether a faster template actually brought more traffic. The page speed help guide covers setup in about two minutes.
Frequently Asked Questions
- What are the Core Web Vitals thresholds?
- Largest Contentful Paint (LCP) is good at 2.5 seconds or less and poor above 4 seconds. Interaction to Next Paint (INP) is good at 200 milliseconds or less and poor above 500 milliseconds. Cumulative Layout Shift (CLS) is good at 0.1 or less and poor above 0.25. Google measures each at the 75th percentile of real page loads, separately for mobile and desktop, and a page passes only when all three are good.
- Do Core Web Vitals affect Google rankings?
- Yes, but modestly. Google states that Core Web Vitals are used by its ranking systems and recommends achieving good scores, but it also says there is no single page experience signal, that it always seeks to show the most relevant content even if page experience is sub-par, and that good scores do not guarantee top rankings. Treat them as a tiebreaker and a conversion issue, not as a replacement for relevant content.
- Why are my PageSpeed Insights and Search Console numbers different?
- They often show different things. PageSpeed Insights shows field data for one URL (or the whole origin when the URL has too little data) plus a Lighthouse lab test from a single simulated load. Search Console groups similar URLs and gives each group the status of its worst metric. Both use the same Chrome User Experience Report data over the last 28 days, but the lab score is a separate simulation and often differs from what real users experience.
- Why doesn't Lighthouse show INP?
- INP measures how quickly the page responds to real clicks, taps and key presses, and a simulated page load has no user to interact with it. Google's documentation says lab tools like Lighthouse cannot measure INP and suggests Total Blocking Time as a lab proxy. To see INP, use field data from the Chrome User Experience Report, PageSpeed Insights or Search Console, or record an interaction yourself in Chrome DevTools.
- How long does it take for Core Web Vitals fixes to show up?
- Field data is a rolling 28-day average, so a fix appears gradually: a few days after deployment the numbers start to move, and the full effect shows after about four weeks. In Search Console, clicking Start tracking on an issue begins a 28-day validation period. Check your lab results right after the deploy to confirm the fix works, then wait for the field data.
Sources
- Web Vitals – web.dev
- Understanding Core Web Vitals and Google search results – Google Search Central
- Understanding page experience in Google Search results – Google Search Central
- Interaction to Next Paint becomes a Core Web Vital on March 12 – web.dev
- Largest Contentful Paint (LCP) – web.dev
- Optimize Largest Contentful Paint – web.dev
- Interaction to Next Paint (INP) – web.dev
- Optimize Interaction to Next Paint – web.dev
- Optimize long tasks – web.dev
- Cumulative Layout Shift (CLS) – web.dev
- Optimize Cumulative Layout Shift – web.dev
- Back/forward cache – web.dev
- Time to First Byte (TTFB) – web.dev
- The most effective ways to improve Core Web Vitals – web.dev
- About PageSpeed Insights – Google for Developers
- CrUX API – Chrome for Developers
- Core Web Vitals report – Search Console Help