The complete guide to Core Web Vitals and technical performance
Core Web Vitals (LCP, INP, CLS) measure loading speed, responsiveness and visual stability using real user data. Most poor scores trace back to a small number of causes — oversized images, render-blocking scripts, missing size attributes, and web fonts — and a small number of fixes resolve most of them.
"Speed up your website" is easy advice to give and hard advice to act on, because speed isn't one thing. It's a composite of what loads, in what order, how much JavaScript runs before the page becomes usable, and whether anything shifts around while a visitor is trying to read or click. Core Web Vitals exist because Google needed a small, standardized set of metrics that actually correlate with how fast a page feels to a real visitor, not just how fast it loads in a lab test with nobody else on the network.
This guide goes deeper than the usual "compress your images and enable caching" advice. It covers what each Core Web Vital actually measures, the specific technical causes behind poor scores, how to read the tools that report on them, and a prioritized order to fix things in — the order that gets you the most improvement for the least work.
What Core Web Vitals actually are
Core Web Vitals are three metrics Google uses as part of its page experience signals: Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS). Each measures a genuinely different aspect of how a page feels to use, and a page can fail badly on one while passing comfortably on the other two — which is exactly why treating "performance" as one number is a mistake.
| Metric | What it measures | Good threshold |
|---|---|---|
| LCP (Largest Contentful Paint) | How long until the largest visible element (usually a hero image or heading) renders | 2.5 seconds or less |
| INP (Interaction to Next Paint) | How long the page takes to visibly respond after a click, tap or keypress | 200 milliseconds or less |
| CLS (Cumulative Layout Shift) | How much visible content unexpectedly shifts position while loading | 0.1 or less |
LCP: what's actually slowing down your biggest element
LCP measures the time from navigation start until the largest content element in the viewport has fully rendered — almost always a hero image, a large heading, or a background video poster on a typical marketing site. A poor LCP score almost never comes from one exotic cause; it comes from a short, predictable list of common culprits.
- •An oversized, uncompressed hero image being downloaded before it can render
- •The hero image loading after render-blocking CSS or JavaScript finishes executing
- •A slow server response time (Time to First Byte) delaying everything downstream
- •A web font that must load before the largest text element can paint
- •The LCP element being lazy-loaded when it shouldn't be, because it's above the fold
Fixing LCP: the practical steps
- 1Compress and correctly size your hero imageServe an image sized for its actual display dimensions, not a full-resolution photo scaled down by CSS. Use a modern format (WebP or AVIF) with a JPEG fallback if needed.
- 2Never lazy-load the LCP elementLazy loading is for below-the-fold images. Applying it to your hero image delays the exact element the metric is measuring — one of the single most common LCP mistakes.
- 3Preload the hero imageA <link rel="preload"> hint tells the browser to fetch the LCP image immediately, in parallel with other early requests, instead of discovering it late in the page's render sequence.
- 4Minimize render-blocking resources above itCSS and synchronous JavaScript that must run before the hero renders should be as small as possible — defer or async anything that isn't needed for the first paint.
- 5Check your hosting's response timeIf Time to First Byte is slow, no amount of front-end optimization fully compensates. A fast static host or CDN-backed hosting matters here.
INP: why a page that loads fast can still feel slow to use
INP measures responsiveness after the page has loaded — the delay between a visitor clicking a button, opening a menu, or typing into a field, and the browser visibly responding. A page can have an excellent LCP and still fail INP badly if the main thread is busy running JavaScript when the visitor tries to interact with it, which is a distinct problem from "the page is slow to load."
- •Long JavaScript tasks blocking the browser's main thread when an interaction happens
- •Heavy third-party scripts (chat widgets, analytics, ad tags) competing for the same thread
- •Large, unoptimized event handlers doing expensive work synchronously on every click
- •Big layout recalculations triggered by a single interaction, like resizing many elements at once
Fixing INP: reducing main-thread work
The general fix for INP is breaking up long-running JavaScript into smaller chunks so the browser gets regular opportunities to respond to input, and reducing the total amount of JavaScript running unnecessarily. For a template-based site with light custom scripting, the highest-leverage fixes are usually auditing third-party scripts (remove ones you don't actually use, load non-critical ones after the main content), and making sure any custom interaction handlers aren't doing expensive work synchronously on every keystroke or click.
CLS: why things jumping around costs you more than you'd think
Cumulative Layout Shift measures how much visible content moves unexpectedly after it's already rendered — the classic example being text you were about to tap that jumps down the page because an ad or image above it just finished loading and pushed everything below it downward. It's frustrating in a way that's disproportionate to how "minor" it sounds, because it actively causes mis-clicks and makes a page feel unstable and unpolished.
| Cause | Fix |
|---|---|
| Images without width/height attributes | Always specify width and height (or aspect-ratio in CSS) so the browser reserves space before the image loads |
| Web fonts causing a visible text reflow | Use font-display: swap or optional, and match fallback font metrics where possible |
| Ads or embeds injected without reserved space | Reserve a fixed-size container for any dynamically inserted content |
| Content inserted above existing content | Avoid injecting banners, cookie notices or promos above content that's already visible, unless the space is pre-reserved |
Image optimization, in more depth
Images are the single largest contributor to page weight on most marketing and template-based sites, which makes image optimization the highest-leverage area of performance work for most small businesses. There are three separate levers, and most sites only pull one or two of them.
- •Format: modern formats like WebP and AVIF produce meaningfully smaller files than JPEG or PNG at equivalent visual quality
- •Sizing: serve an image at the resolution it's actually displayed at, using responsive srcset variants for different screen sizes, not one oversized file for everyone
- •Compression: even within a format, quality settings matter — most images can be compressed well beyond their default export quality with no visible difference
Fonts: a frequently overlooked performance cost
Web fonts add a render-blocking dependency if not handled carefully — the browser may wait for a custom font file to download before showing any text at all, or swap fonts abruptly once it arrives, contributing to layout shift. A few practical fixes address most of this: limit yourself to one or two font families and a small number of weights (each weight is a separate file to download), self-host fonts rather than pulling them from a third-party service where possible, and use font-display: swap so text appears immediately in a fallback font rather than staying invisible while the custom font loads.
Caching and CDNs: making the second visit (and the first) faster
Browser caching tells a returning visitor's browser to reuse files it already downloaded instead of re-fetching them, which meaningfully speeds up repeat visits and multi-page browsing within the same site. A Content Delivery Network (CDN) serves your site's files from a location physically closer to each visitor, which reduces the latency of that first request regardless of whether they've ever visited before. Most modern static hosting providers (Cloudflare Pages, Netlify, Vercel and similar) include CDN distribution and sensible caching by default, which is a meaningful, often invisible performance advantage that static template sites get largely for free compared to server-rendered alternatives.
Lab data vs. field data: why your scores don't always match
This is the single most common source of confusion when people start checking their Core Web Vitals, so it's worth explaining clearly. Lab data is generated by running a single, simulated test — for example, Lighthouse running once on one device profile with one simulated network speed. Field data (also called Real User Monitoring, or CrUX — the Chrome User Experience Report) is aggregated from actual visits by real people, on their real devices and real network conditions, over a rolling 28-day period.
| Lab data | Field data (CrUX) | |
|---|---|---|
| Source | A single simulated test run | Aggregated real visitor data |
| Consistency | Reproducible, same conditions every time | Varies with real devices and networks |
| Best for | Debugging a specific issue, testing a fix before deploying | Understanding what your actual visitors experience |
| Limitation | Doesn't reflect the range of real-world conditions | Requires enough traffic to generate data; can't test a page that isn't live yet |
This is why a page can pass in one tool and show warnings in another, or why your Lighthouse score in a private browser tab looks great while Google Search Console reports "needs improvement" for the same URL — they're measuring different things. Use lab data while you're actively working on a fix, and field data to judge how the page performs for actual visitors once it's live.
The tools, and what each one is actually for
| Tool | Data type | Best used for |
|---|---|---|
| PageSpeed Insights | Both lab and field (CrUX) data on one report | The best single starting point — shows real-world field data when available, lab data always |
| Lighthouse (in Chrome DevTools) | Lab only | Debugging a specific page locally, testing a fix before it goes live |
| Google Search Console (Core Web Vitals report) | Field only | Seeing how Google is grading your actual indexed pages, grouped by issue type |
| GTmetrix | Lab, with more configuration options | Testing from specific locations/devices, deeper waterfall analysis |
A prioritized action checklist
Not all fixes are equal. If you're starting from a poor score and have limited time, this is roughly the order of highest-impact-to-effort ratio.
- 1Compress and correctly size every image on the pageUsually the single biggest win available, and the easiest to do without touching any code logic.
- 2Add width/height to every image and reserve space for embedsDirectly targets CLS and is a simple, mechanical fix once you know to look for it.
- 3Audit third-party scripts and remove what you don't useChat widgets, old analytics snippets and unused tracking pixels are a common, easy-to-miss INP cost.
- 4Preload your LCP element and avoid lazy-loading itDirectly targets your largest above-the-fold element's render time.
- 5Limit font families/weights and set font-display: swapReduces both render-blocking risk and layout shift from font swaps.
- 6Confirm your host provides CDN distribution and browser cachingA one-time check that pays off on every subsequent visit from every visitor.
Why static, template-based sites start from an advantage
A static HTML/CSS site has no database query, no server-side rendering step, and no plugin ecosystem accumulating JavaScript over time — all common sources of poor performance on CMS-driven sites. This doesn't make a template automatically pass Core Web Vitals; a bloated template with unoptimized images and five embedded third-party widgets can still fail badly. But it does mean the ceiling is higher and the effort required to reach a genuinely fast result is lower, because there's less inherited complexity working against you before you've made a single optimization.
How Core Web Vitals affect rankings, realistically
Core Web Vitals are one of many page experience signals Google factors into ranking, and they matter more as a tiebreaker between otherwise similar pages than as a dominant ranking factor on their own — a page with mediocre performance but genuinely better, more relevant content will still generally out-rank a lightning-fast page that doesn't answer the query well. The realistic framing is that poor Core Web Vitals put a ceiling on how well a page can perform, and good ones remove that ceiling; they rarely single-handedly win or lose a ranking on their own.
- ✓LCP, INP and CLS each measure a different aspect of page experience — a page can fail one and pass the others.
- ✓Oversized images, render-blocking scripts and missing image dimensions cause the majority of poor scores.
- ✓Never lazy-load your largest above-the-fold element — it directly delays the metric.
- ✓Field (CrUX) data reflects real visitors over 28 days; lab data reflects one simulated test run — use both, for different purposes.
- ✓Fix images, layout shift and third-party scripts first — that order gets the most improvement for the least effort.
- ✓Static, template-based sites start with a lower-complexity baseline, but still require deliberate optimization to actually pass.