Core Web Vitals in 2026: LCP, INP and CLS Explained, With Fixes
Published · 9 min read
Core Web Vitals are three numbers Google uses to describe how a page feels to a real visitor: Largest Contentful Paint (LCP) for loading, Interaction to Next Paint (INP) for responsiveness, and Cumulative Layout Shift (CLS) for visual stability. A page passes when all three are in the “good” range at the 75th percentile of real user visits. This article gives the documented thresholds, explains which data set Google actually uses, and ranks the fixes that usually move each metric most.
The three metrics and Google's thresholds
The thresholds below are the ones Google publishes on web.dev. They have not changed since INP replaced First Input Delay as the responsiveness metric in March 2024. Each metric has a “good” band, a “needs improvement” band, and a “poor” band.
| Metric | What it measures | Good | Needs improvement | Poor |
|---|---|---|---|---|
| LCP | Time until the largest image or text block in the viewport has rendered | ≤ 2.5 s | 2.5 s – 4.0 s | > 4.0 s |
| INP | Delay between a click, tap or key press and the next frame painted, reported as one of the slowest interactions of the whole visit | ≤ 200 ms | 200 ms – 500 ms | > 500 ms |
| CLS | Total unexpected movement of visible content, as a unitless score | ≤ 0.1 | 0.1 – 0.25 | > 0.25 |
Note that LCP is about one element, not the whole page, and INP is not an average: one slow menu or filter can fail a page that is otherwise quick.
Field data vs lab data: which number Google uses
Google evaluates Core Web Vitals on field data: measurements collected from real Chrome users who have opted in, aggregated in the Chrome User Experience Report (CrUX). CrUX reports the 75th-percentile value over a rolling 28-day window, per URL where there is enough traffic and otherwise per origin. Google's page experience documentation describes this field data as the basis for the Core Web Vitals signal in search.
Lab data is what Lighthouse produces: one synthetic load of one URL on a simulated slow device and network. It is repeatable and it comes with diagnostics, which makes it the better debugging tool. It is not what search uses, and it has one hard gap: Lighthouse does not click anything, so it cannot measure INP. It reports Total Blocking Time instead, which correlates with INP but is not the same number.
| Property | Field data (CrUX) | Lab data (Lighthouse) |
|---|---|---|
| Source | Real Chrome visits, opted in | One simulated load |
| Statistic | 75th percentile over 28 days | Single run |
| Where to see it | Search Console Core Web Vitals report, PageSpeed Insights top section, CrUX API | PageSpeed Insights lower section, Chrome DevTools, Lighthouse CLI |
| Measures INP | Yes | No (reports Total Blocking Time) |
| Used for search | Yes | No |
| Low-traffic pages | May have no data at all | Always available |
If PageSpeed Insights says “no field data” for a URL, Google has nothing to assess that page on individually and falls back to origin-level data if it exists. A Lighthouse score of 100 says the page can be fast; only field data says whether it is.
LCP: what slows it and what to fix first
LCP is a chain: the server has to respond, the browser has to find the largest element, fetch it, and paint it. Each link can add time. The fixes below are ordered by how much they usually move the number, in our experience; your profile may differ, and the Performance panel in Chrome DevTools will show which phase is longest for your page.
- Slow server response. Nothing renders before the first byte arrives, so a slow origin caps every other fix. Full-page caching, a CDN in front of the origin, and fewer database calls per request are the usual wins. This is the one part of LCP that a plain HTTP request can observe.
- Render-blocking CSS and JavaScript. Stylesheets in
<head>block painting until they download. Inline the CSS the first screen needs, load the rest asynchronously, and putdeferon scripts that do not have to run before paint. - The hero image itself. Three separate problems hide here. The image may be too large in bytes (compress it, serve WebP or AVIF, use
srcset). It may be discovered late because it is a CSS background or is injected by JavaScript. Or it may be lazy-loaded, which is exactly wrong for the largest element above the fold. - Client-side rendering. If the largest element only exists after a JavaScript bundle runs, LCP waits for that bundle. Server-render or statically generate the first screen.
For the hero image, make it discoverable from the HTML and tell the browser it matters:
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high">
<img src="/hero.webp" width="1200" height="630" alt="…"
fetchpriority="high" decoding="async">Do not put loading="lazy" on that image. Lazy loading is for images below the fold.
INP: what makes pages feel sluggish
INP measures the gap between an interaction and the next visual update. That gap is almost always the browser's main thread being busy. Three causes account for most poor INP scores.
- Long tasks. Any script that runs for more than 50 ms without yielding delays every interaction that arrives while it runs. Third-party tags (analytics, chat widgets, consent managers, A/B testing) are the most common source because they load early and run a lot. Audit them, defer what can wait, remove what nobody reads.
- Heavy event handlers. A click handler that filters a large list, reads layout, and then writes to the DOM in one go blocks the frame until it finishes. Do the minimum synchronously, update the UI, and yield before the expensive work.
- Hydration. Framework sites ship HTML that looks interactive before the JavaScript that makes it interactive has run. Clicks during that window are queued and answered late. Less client-side JavaScript is the real fix: server components, partial hydration, or islands, depending on the framework.
The yielding pattern is small. Paint first, then do the work in a later task:
button.addEventListener("click", () => {
button.textContent = "Saving…"; // visible right away
setTimeout(() => {
doExpensiveWork(); // runs after the next paint
}, 0);
});CLS: why content jumps
Layout shift happens when something above a piece of content changes size after that content has rendered. The causes are more mechanical than for the other two metrics, and the fixes are mostly about reserving space.
- Images, videos and iframes without dimensions. Without
widthandheightattributes (or a CSSaspect-ratio), the browser lays the element out at zero height and then pushes everything down when the file arrives. This is the most common cause and the cheapest fix. - Late-loading web fonts. When a fallback font renders first and the web font swaps in with different metrics, text reflows. Preload the font file, use
font-display: swaporoptional, and tune the fallback withsize-adjustso the swap is visually close. - Ads, embeds and banners injected above content. Ad slots, cookie notices, and “app install” bars that appear after load and push the page down. Give each slot a fixed
min-height, or overlay the banner instead of inserting it into the flow. - Animating layout properties. Animating
top,left,heightormarginmoves neighbors. Animatetransformandopacityinstead; they do not affect layout.
<!-- Reserves the box before the file arrives -->
<img src="/chart.png" width="800" height="450" alt="…">
<!-- Same idea in CSS for responsive images -->
img { width: 100%; height: auto; aspect-ratio: 16 / 9; }Shifts that happen within 500 ms of a user interaction do not count toward CLS, so a menu expanding on click is fine. Shifts with no interaction behind them are what the metric catches.
How to measure for free
None of the tools that matter cost money. Use the field tools to decide whether you have a problem and the lab tools to find where it is.
- PageSpeed Insights at pagespeed.web.dev. Field data on top when CrUX has it, a Lighthouse run underneath. Start here.
- Search Console, Core Web Vitals report. Groups your URLs into good, needs improvement and poor by the same CrUX data, so you can see which templates fail rather than one page at a time. Requires a verified property.
- CrUX Dashboard and CrUX API. The raw field data, by origin or URL, month by month. Useful for tracking a trend after a fix ships.
- Chrome DevTools, Performance panel. Shows live LCP, INP and CLS for the page you have open, with the LCP element and each layout shift highlighted. This is where you find the specific cause.
- The
web-vitalsJavaScript library. Google's own library for collecting the three metrics from your visitors and sending them to your analytics. It is the way to get field data for pages CrUX does not cover.
What Aura's free scan does and does not check
The free scan on this site does not measure Core Web Vitals. It takes one server response-time sample for the page you enter and gives full marks under 1.5 seconds, with a warning above that. That is a reasonable proxy for the first link of the LCP chain, the server response, and nothing more. It does not render the page in a browser, so it cannot see the hero image, the main thread, or layout shifts, and it has no real-user data to draw on.
For the real thing, use PageSpeed Insights. What the scan does check is the structural layer that sits next to performance in a technical audit: HTTPS and a clean 200 at the final URL, a single H1, valid JSON-LD, a canonical tag, and the rest of the 18 checks described here. Those checks and Core Web Vitals are both part of a technical SEO checklist; they are just measured differently. If you are working through a site in one sitting, the one-hour SEO audit shows where vitals fit in the order of operations.
The reason to fix vitals is that slow, jumpy pages lose visitors in every channel, including the AI search surfaces discussed in SEO rankings vs AI visibility. The ranking effect, in our reading, is secondary.
Frequently asked questions
What counts as a good LCP, INP and CLS score?
Google's documented thresholds are: LCP good at 2.5 seconds or less and poor above 4 seconds; INP good at 200 milliseconds or less and poor above 500 milliseconds; CLS good at 0.1 or less and poor above 0.25. A page passes when all three are in the good range at the 75th percentile of real user visits.
Do Core Web Vitals affect Google rankings?
Google's page experience documentation says its ranking systems use Core Web Vitals as one signal among many. In our reading it is a secondary signal: relevant, well-linked content with poor vitals still outranks thin content with perfect vitals. Fix them because slow pages lose users; treat the ranking effect as a bonus.
Why does PageSpeed Insights show different numbers from Lighthouse?
PageSpeed Insights shows two data sets. The field section comes from the Chrome User Experience Report: real visits over the last 28 days, reported at the 75th percentile. The lab section is a single Lighthouse run on a throttled simulated device. Google uses the field data for search; Lighthouse is a diagnostic tool, and it does not measure INP at all.
Does Aura's free scan measure Core Web Vitals?
No. The free scan takes one server response-time sample for the page and gives full marks under 1.5 seconds. It does not render the page in a browser and has no real-user data, so it cannot measure LCP, INP or CLS. Use PageSpeed Insights or the Core Web Vitals report in Search Console for those.