Core Web Vitals: What They Are and How to Improve Them
A practical guide to Google's Core Web Vitals — LCP, INP, and CLS. Learn what each metric measures, what thresholds to hit, and the specific fixes that move the needle.
Why Core Web Vitals matter more than ever
Core Web Vitals are Google's way of saying: if your site is slow, janky, or unresponsive, we'll rank it lower. That statement has been true since 2021, but the stakes have risen as mobile traffic has grown to dominate most verticals. A page that loads beautifully on a developer's MacBook over fiber can be genuinely unusable on a mid-range Android phone over a patchy 4G connection — and that phone user is now the majority of your audience.
The three metrics are LCP (Largest Contentful Paint), INP (Interaction to Next Paint), and CLS (Cumulative Layout Shift). Each measures a different aspect of the user's experience: how fast something meaningful appears, how quickly the page responds when they interact with it, and how stable the layout is while it loads. Google publishes clear thresholds for each, and hitting all three puts you in a better position than roughly 60% of the web.
LCP: how fast does the main content appear?
Largest Contentful Paint measures how long it takes for the largest visible element — typically a hero image, a heading, or a background video — to render on screen. The threshold is 2.5 seconds. Under that, you pass. Between 2.5 and 4 seconds, you need improvement. Over 4, Google considers the experience poor.
The most common LCP killers are hero images that aren't optimized, render-blocking CSS or JavaScript that delays painting, slow server response times (TTFB), and lazy-loading the LCP element itself — which is counterproductive since the browser delays loading the most important thing on the page.
- Preload the LCP image: add <link rel='preload'> for your hero image so the browser starts fetching it immediately instead of waiting until it parses the HTML that references it
- Serve images in WebP or AVIF: these formats are 25–50% smaller than JPEG/PNG at the same visual quality
- Eliminate render-blocking scripts: defer non-critical JavaScript and inline critical CSS
- Reduce server response time: if TTFB is over 600ms, look at your hosting, caching layer, or database queries before optimizing the frontend
- Don't lazy-load above-the-fold content: lazy loading is for images below the viewport. Apply it to the LCP image and you guarantee a bad score
INP: does the page feel responsive?
Interaction to Next Paint replaced First Input Delay (FID) in March 2024 and is a harder metric to pass. Where FID measured only the delay before the browser starts processing your first interaction, INP measures the worst-case delay across all interactions during the entire page visit — every tap, click, and keypress. The threshold is 200 milliseconds.
The usual culprits are heavy JavaScript execution that blocks the main thread, poorly optimized event handlers, and third-party scripts (analytics, chat widgets, ad tags) that run expensive operations on every interaction. The fix pattern is consistent: break up long tasks, defer non-essential work, and move heavy computation off the main thread with web workers.
- Audit third-party scripts: remove any you're not actively using, defer the rest, and measure the before/after impact
- Break up long tasks: any JavaScript task over 50ms blocks the main thread. Use requestIdleCallback or setTimeout(0) to yield back to the browser between chunks
- Debounce input handlers: scroll, resize, and rapid-fire input events should use requestAnimationFrame or a debounce wrapper
- Use CSS containment: content-visibility: auto on off-screen sections lets the browser skip layout work until the user scrolls there
CLS: does the layout stay still?
Cumulative Layout Shift measures how much visible content moves around unexpectedly while the page loads. The threshold is 0.1. Above that, users are dealing with the infuriating experience of trying to click a button that jumps away just as they reach for it, typically because an ad, image, or font loaded late and pushed everything down.
CLS is the easiest Core Web Vital to fix because the solutions are almost entirely preventive. Set explicit dimensions on every image and video element. Reserve space for ads and embeds before they load. Preload custom fonts and use font-display: swap or optional to avoid invisible text flashing into place.
- Always set width and height (or aspect-ratio) on images: this lets the browser reserve the correct space before the image downloads
- Reserve space for dynamic content: ads, iframes, and cookie banners should have predetermined heights so they don't push content down when they appear
- Preload fonts: late-loading web fonts cause a layout shift when text reflows from the fallback font to the custom one. Preload your font files and use font-display: swap
- Avoid injecting content above existing content: any DOM insertion above the viewport causes a shift. If you must add banners or notices, push them to fixed positions or the top of the document before initial paint
How to measure and track your scores
Google provides Core Web Vitals data in three places: PageSpeed Insights (lab data for a single URL), Chrome User Experience Report (real-user field data, available in Search Console), and the web-vitals JavaScript library (real-user monitoring you can pipe into your own analytics). Lab data is useful for debugging specific pages; field data is what Google actually uses for ranking.
For a site-wide view, WebEnture's Performance Agent (/performance-agent) crawls multiple pages and reports aggregate performance patterns — total page weight, request count, render-blocking resources, and image optimization gaps — so you can prioritize fixes by how many pages they affect rather than optimizing one URL at a time. Run it after every major deploy to catch regressions before they reach enough users to hurt your CrUX scores.