What Are Core Web Vitals? LCP, INP and CLS Explained with Practical Fixes

Core Web Vitals are the three metrics Google uses to describe real user experience on a page: LCP for loading, INP for responsiveness and CLS for visual stability. I have worked with these numbers on client sites for years, and I have been in digital marketing since 2012. In this guide I explain what each metric means, where the thresholds sit and how to fix each one.
I have already covered the broader SEO impact of speed in how site speed affects SEO. The testing workflow lives in my Lighthouse performance test guide. This article stays focused on the three metrics themselves.
What are Core Web Vitals and why do they matter?
Core Web Vitals are three Google metrics that measure how fast the main content of a page loads, how quickly the page responds to input and how stable the layout stays while it loads. Google collects them from real Chrome users and uses them as part of its page experience signals in search.
They matter for two reasons. First, search: Google states in its Search Central documentation that its ranking systems use Core Web Vitals. Second, people. A page that loads slowly, reacts late to a tap or moves a button away from your thumb quietly loses visitors. So these metrics are not only an SEO score. They also measure friction at the very top of your sales funnel.
The most common misconception I meet is that Core Web Vitals are a one-off technical task. In practice, every new plugin, campaign banner and tracking tag can break them again. That is why I treat them as a health indicator you watch every month, not as a project you close.
Which three metrics make up Core Web Vitals?
The current set has three metrics, and each one covers a different part of the experience. According to the official definitions on web.dev, the thresholds look like this:
| Metric | What it measures | Good | Needs improvement | Poor |
|---|---|---|---|---|
| LCP (Largest Contentful Paint) | Loading of the main content | 2.5 s or less | 2.5 to 4 s | Over 4 s |
| INP (Interaction to Next Paint) | Response to interactions | 200 ms or less | 200 to 500 ms | Over 500 ms |
| CLS (Cumulative Layout Shift) | Visual stability | 0.1 or less | 0.1 to 0.25 | Over 0.25 |
One detail matters a lot. A page only passes when all three metrics sit in the good range. For example, if LCP and CLS look great but INP is poor, Search Console still flags that URL group as poor. In addition, Google assesses these thresholds at the 75th percentile, not the average. I come back to that below, because many teams look at averages and draw the wrong conclusion.
The set also changes over time. INP replaced FID in March 2024, for instance. In short, web.dev should always be your source for the current thresholds.
What is LCP and what counts as a good LCP score?
LCP, or Largest Contentful Paint, marks the moment the largest visible content element in the viewport finishes rendering. The web.dev LCP guide sets the good threshold at 2.5 seconds or less. Anything over 4 seconds is poor.
The LCP element is usually one of these:
- The hero image or a large product photo.
- A large background image you set through CSS.
- The poster image of a video.
- A large heading or text block on pages without images.
I like this metric because it sits close to what people actually feel. A visitor decides that a page "has loaded" when they see the main content. However, LCP varies a lot by device. A page that shows 1.2 seconds on a desktop with fibre can easily cross 4 seconds on a mid-range Android phone over mobile data.
So always read mobile and desktop data separately. Google reports them separately too. In most of my projects, mobile LCP ends up as the first priority, because that is where most of the traffic comes from.
Why is LCP slow on so many sites?
Before you fix LCP, you need to know where the time goes. web.dev splits LCP into four sub-parts, and that split makes diagnosis much easier:
- Time to first byte (TTFB): how long the server takes to send its first response.
- Resource load delay: how long the browser waits before it discovers and requests the LCP image.
- Resource load duration: how long the image itself takes to download.
- Element render delay: how long it takes to paint the element after the download ends.
In the field, the second item causes most trouble. For example, a slider that injects the hero image with JavaScript hides that image from the browser while it parses the HTML. The browser has to wait for the script first. Likewise, adding lazy loading to the LCP image by mistake delays discovery.
The first item usually hurts on cheap shared hosting or on dynamic pages without caching. If the server builds each page from the database on every request, TTFB alone can eat a full second. Therefore, start by finding the dominant sub-part. Do not jump straight to image compression.
How do you improve LCP?
Once you know the cause, the fixes are fairly clear. These are the steps I use most often:
- Put the LCP image directly in the HTML as an img tag; do not inject it with JavaScript.
- Add fetchpriority="high" to that image and remove lazy loading from it.
- Serve the image in a modern format such as WebP or AVIF, at its real display size.
- Reduce TTFB with page caching on the server and a CDN.
- Cut render-blocking CSS and synchronous scripts.
- Preload key web fonts so a text-based LCP does not wait.
Here is a simple size check. If you serve a 1920 pixel wide photo into a 400 pixel mobile slot, you download a file several times larger than needed. In that case, create a correctly sized version with an image resizer and then use srcset to serve different files to different screens.
That said, do not change everything at once. Ship one change, watch field data for a few weeks and then move to the next. That way you learn which step actually worked.
What is INP and why did it replace FID?
INP, or Interaction to Next Paint, measures how long the page takes to show the next visual update after a click, tap or key press. The web.dev INP guide treats 200 milliseconds or less as good. Anything over 500 milliseconds is poor.
INP became a Core Web Vital on 12 March 2024 and replaced FID (First Input Delay). The logic behind the change is simple. FID only looked at the delay before the browser started handling the first interaction. It ignored how long that work took, and it ignored every later interaction.
INP, on the other hand, observes interactions across the whole page visit and reports one of the slowest. As a result, it is a far more honest metric. I saw this in practice: under FID almost every site looked fine. When INP arrived, many JavaScript-heavy online shops dropped into amber and red overnight.
Put simply, INP shows how smooth your site feels while people browse, filter products or add items to the cart. From a conversion point of view, it has become the metric I care about most.
Which interactions hurt INP the most?
Poor INP almost always comes from work that keeps the main thread busy. The browser uses one main thread to run JavaScript and to paint the screen. So if a long script runs while a user clicks, that click waits in line.
These are the problem cases I see most often:
- Category pages that recalculate the whole product list whenever someone picks a filter.
- A menu button that triggers a heavy animation library.
- An add-to-cart button that fires several tracking tags at the same moment.
- Form fields that run validation and suggestion scripts on every keystroke.
- Third-party scripts such as chat widgets, pop-ups and cookie banners loading in the background.
Keep one thing in mind. Lab tests do not click on anything, so these problems often stay invisible there. Lighthouse shows Total Blocking Time (TBT) as a proxy instead of INP. A high TBT usually means INP has a problem too. Still, a low TBT does not prove that INP is good. Only field data shows the real picture.
How do you improve INP?
web.dev breaks each interaction into three parts: input delay, processing duration and presentation delay. Your strategy depends on which part runs long.
If input delay runs long, the main thread is busy with other work when the user clicks. In that case, break up long tasks during page load and defer third-party scripts you do not need right away. If processing duration runs long, the event handler itself does too much. For instance, showing visual feedback immediately and moving heavy work to the next frame often makes a big difference.
Presentation delay usually appears when the DOM grows very large. On a page with thousands of elements, even a single class change forces a costly recalculation. Therefore, I recommend virtualisation or pagination for very long lists.
Deep JavaScript optimisation deserves its own article, so I keep it high level here. In practice my first step never changes: I list every third-party script on the site and ask whether anyone still uses it. On most projects we remove about half, and INP relaxes almost immediately.
What is CLS and how does Google calculate it?
CLS, or Cumulative Layout Shift, measures how much visible content moves unexpectedly while the page is open. According to the web.dev CLS guide, 0.1 or less is good and anything over 0.25 is poor. It has no unit; it is a score, not a time.
For each shift, the browser multiplies two values: the share of the viewport the moving elements cover and the distance they travel. It then groups shifts that happen close together into "session windows". A window lasts at most 5 seconds, and a gap of more than 1 second starts a new one. Your CLS value comes from the window with the highest total during the page visit.
There is one more important rule. Shifts within 500 milliseconds of a user interaction do not count. So content that expands after someone taps "show more" is fine. The problem is content that moves while the user does nothing.
We have all lived the classic example. You are about to tap a link on a news site, an ad loads above it, the content jumps and you tap the wrong thing. CLS turns exactly that frustration into a number.
How do you reduce CLS?
CLS is usually the easiest of the three to fix, because the causes look familiar. My checklist goes like this:
- Give every image and video width and height attributes, or reserve space with CSS aspect-ratio.
- Reserve fixed-height slots for ads, embeds and iframes before they load.
- Show the cookie banner as an overlay, not as a block that pushes content down.
- Tune font-display and fallback font metrics to limit text shifts when web fonts arrive.
- Avoid inserting new content above existing content; keep notification bars in a fixed area.
Animations are another blind spot. Animating properties such as top or margin can cause layout shifts. Animations that use transform do not. In addition, the back/forward cache (bfcache) helps, because it restores the page instantly without a new layout.
Since these fixes sit close to design, it costs far less to handle CLS from the start of a new build or redesign. In my web design projects I fix image slots and banner areas during the design phase. That way nobody has to patch them later.
What is the difference between field data and lab data?
This is the part that confuses people most. Field data comes from real Chrome users who visit your site. Lab data comes from a synthetic test on one device and one simulated network.
| Aspect | Field data | Lab data |
|---|---|---|
| Source | Real users (CrUX) | A single simulated test |
| Typical tools | Search Console, top section of PageSpeed Insights | Lighthouse, Chrome DevTools |
| INP | Available | Not available; TBT acts as a proxy |
| Refresh | Rolling 28-day window | Instant |
| Best use | Assessing status | Diagnosing causes |
Google looks at field data for ranking. So a Lighthouse score of 95 does not mean Search Console will show green. The opposite also happens. A slow test device can give you a low lab score while your real visitors, on faster phones, enjoy good field numbers.
My rule is simple: measure status with field data and find causes with lab data. Never swap one for the other.
Why does Google use the 75th percentile?
Google assesses Core Web Vitals at the 75th percentile, not the average. In other words, for a page to have good LCP, at least 75 percent of visits need an LCP of 2.5 seconds or less.
This choice is deliberate, because averages hide outliers. Here is an example calculation. If half of your visitors see the page in 1 second and the other half in 4 seconds, the average is 2.5 seconds and everything looks fine. Yet half your users have a bad experience. The 75th percentile makes that slow group visible.
In practice this means you should optimise for mid-range and low-end devices, not for your fastest ones. Older phones and weak mobile connections usually define the 75th percentile. That is why I recommend turning on CPU and network throttling in DevTools as a habit.
Google also assesses mobile and desktop separately. If desktop shows green and mobile shows red, the mobile result is the one that applies to mobile search.
Which tools should you use to track Core Web Vitals?
I group my Core Web Vitals tools by purpose:
- Google Search Console: field status by URL group across the whole site. This is the starting point for a health check.
- PageSpeed Insights: CrUX field data and a Lighthouse lab run for a single URL on one screen.
- CrUX Vis and the CrUX API: historical trends by origin or by page.
- Chrome DevTools Performance panel: live LCP, INP and CLS values while you interact locally.
- The web-vitals JavaScript library: real user data from your own visitors, sent to your analytics tool.
The last option is the least used and, in my view, the most valuable. Because CrUX uses a 28-day window, it takes weeks to see the effect of a fix. With your own measurement you see results within days. You can also tell which template or which interaction causes the problem.
Low-traffic pages may show no CrUX data at all. That means Google does not have enough samples yet. Consequently, your own measurement becomes the only reliable source.
How do you read the Core Web Vitals report in Search Console?
The Search Console report groups similar pages instead of listing URLs one by one. Google's help page for the report explains this grouping. For example, all your product pages may share one template and end up in a single group.
I read the report in a fixed order. First I open the mobile tab, because that is where most traffic comes from. Then I open the "Poor" and "Need improvement" groups to see which metric causes the issue. A group takes the status of its worst metric.
Next I open a sample URL from that group in PageSpeed Insights and move to lab diagnosis. After you ship a fix, you can press "Validate fix" in the report. However, validation starts a 28-day monitoring period, so do not expect an instant answer.
I explain the rest of the tool in my Google Search Console guide. The Core Web Vitals report is only one part of that toolkit.
How much do Core Web Vitals affect rankings?
The honest answer: they have an effect, but they do not beat relevance. Google says its ranking systems use Core Web Vitals. At the same time, its page experience documentation stresses that a good page experience alone does not guarantee top rankings and that relevance comes first.
My reading from the field is this. Core Web Vitals act as a tie-breaker between pages of similar quality. The page with the best answer can keep ranking even if it runs a little slow. But if you and a competitor offer equally strong content, the experience gap starts to matter.
Meanwhile, the indirect effect is much larger than the ranking effect. On a slow, jumpy page, people leave sooner, view fewer pages and convert less. I cover that side in how to reduce bounce rate on a business website.
In short, treat Core Web Vitals as basic hygiene for both search and users, not as a ranking trick. You can find the other page experience factors in my article on SEO and UX page experience factors.
In what order should you plan the work?
Many teams start with the most visible page, the homepage. Yet most traffic and revenue usually comes from category, product or service templates. This is the order I recommend:
- Open the mobile report in Search Console and list the URL groups rated poor.
- Rank those groups by traffic and revenue contribution.
- Identify which metric fails on the template of your most valuable group.
- Diagnose the sub-parts of that metric with PageSpeed Insights and DevTools.
- Ship one fix at a time.
- Track results for a few days with your own data and for a few weeks with CrUX.
- Move to the next group once you confirm the result.
The advantage of this order is that it thinks in templates. Once you fix a hero image problem on the product template, you fix thousands of pages at once. You also start where business impact is highest, which makes reporting to management much easier.
If you want to place this work inside a broader plan, my technical SEO tips give you a useful frame.
Which mistakes waste Core Web Vitals work?
Over the years I have seen the same mistakes on very different projects. These are the most common:
- Chasing a Lighthouse score and never checking field data.
- Installing a speed plugin that lazy loads every image, including the LCP image.
- Testing only on desktop and ignoring mobile users.
- Expecting Search Console to change the day after a fix.
- Ignoring tracking tags and pop-ups that marketing adds later.
The last one costs the most. A developer spends months getting the numbers into the green. Then a new campaign adds three scripts and a full-screen pop-up, and everything goes back to square one. That is why Core Web Vitals need to be a shared responsibility of developers and marketers.
Another frequent mistake is blind trust in speed plugins. They sometimes help. However, with the wrong settings they can load CSS late and raise CLS, or defer scripts and break interactions. Measure after every settings change.
Why are Core Web Vitals harder on mobile?
Mobile devices vary much more than desktops in processing power, memory and network conditions. The same JavaScript bundle that runs in a few hundred milliseconds on a strong laptop can take several times longer on a mid-range phone. That gap shows up directly in INP.
The network tells a similar story. Mobile connections have higher latency, so every extra request, redirect and third-party domain adds real time to LCP. For example, a language redirect before the homepage loads can create a noticeable delay for mobile users on its own.
So do not think of mobile design as a desktop page squeezed onto a small screen. Removing sliders, heavy animations and oversized images that mobile users do not need often improves all three metrics at once. For a general mobile check, see my mobile-friendly test guide.
How do you keep Core Web Vitals results from slipping?
Getting the numbers green once is the easy part. Keeping them green is harder, so I recommend a few lasting habits.
First, set a performance budget. For example, cap the total JavaScript size on the homepage and the file size of the LCP image. If a new feature breaks the budget, the team decides what to remove before adding it. As a result, performance becomes part of every design and marketing decision.
Second, automate measurement. Send the data you collect with the web-vitals library to your analytics tool and review it weekly. In addition, a check such as Lighthouse CI in your release process catches regressions before they go live.
Third, limit who can add third-party scripts. If everyone with Tag Manager access can add code, you do not really control performance.
If you would rather not run this alone, I include Core Web Vitals monitoring in the monthly routine of my SEO consulting work.
Where should you start with Core Web Vitals today?
To sum up, Core Web Vitals measure three basic experiences: how quickly people see the main content, how quickly the page responds when they act and how stable it stays. The thresholds are clear: 2.5 seconds for LCP, 200 milliseconds for INP and 0.1 for CLS.
The most useful step you can take today is to open the mobile report in Search Console and find the failing metric on your most valuable template. Then diagnose its sub-parts and start with one fix. Do not chase a perfect score. Instead, aim for a good experience for at least 75 percent of your real users. After all, that is what both Google and your customers reward.




