Core Web Vitals: How to Measure and Improve Them
Why Core Web Vitals Matter for Your Site
You've probably seen reports that your site is slow, but you're not sure where to start. Core Web Vitals are Google's metrics for real-world user experience: Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS). They affect search rankings and, more importantly, how users perceive your site. A slow LCP frustrates visitors, a high INP makes the page feel unresponsive, and a poor CLS causes accidental clicks. This guide shows you how to measure these metrics and improve them with practical steps.
Understanding the Three Core Web Vitals
Before optimizing, know what each metric measures and its thresholds.
| Metric | What it measures | Good | Needs improvement | Poor |
|---|---|---|---|---|
| LCP | Time until the largest content element (image, text block) is rendered | ≤ 2.5 s | 2.5–4.0 s | > 4.0 s |
| INP | Time from user interaction to the next paint | ≤ 200 ms | 200–500 ms | > 500 ms |
| CLS | Sum of layout shift scores for unexpected visual moves | ≤ 0.1 | 0.1–0.25 | > 0.25 |
These thresholds are based on field data (real users), not lab tests. Aim for the "Good" range for at least 75% of page loads.
How to Measure Core Web Vitals
You need both lab and field data. Lab data helps you debug; field data reflects real user experience.
Lab Tools
- Lighthouse in Chrome DevTools: run an audit for performance scores and specific opportunities.
- WebPageTest: advanced testing with filmstrips and waterfall charts.
- Chrome UX Report (CrUX): field data from real users, accessible via PageSpeed Insights or the CrUX API.
Field Tools
- PageSpeed Insights: shows both lab and field data for a URL.
- Google Search Console: Core Web Vitals report groups URLs by status.
- web-vitals JavaScript library: collect real user metrics in your own analytics.
To instrument your site, include the web-vitals library and send metrics to your analytics endpoint:
import {onLCP, onINP, onCLS} from 'web-vitals';
function sendToAnalytics(metric) {
const body = JSON.stringify(metric);
navigator.sendBeacon('/analytics', body);
}
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
This gives you a continuous stream of field data to track improvements.
Improving Largest Contentful Paint (LCP)
LCP is often the biggest challenge. The largest element is usually a hero image or a large text block. Optimize its loading path.
- Identify the LCP element using Lighthouse or DevTools performance panel.
- Prioritize its loading: use
fetchpriority="high"on the image or preload it with<link rel="preload">. - Optimize images: compress, use modern formats (WebP/AVIF), and serve responsive sizes with
srcset. - Reduce server response time: use caching, a CDN, and optimize backend queries.
- Eliminate render-blocking resources: inline critical CSS, defer non-critical JS.
Example: preload the hero image and set fetch priority:
<link rel="preload" as="image" href="/hero.avif" fetchpriority="high">
<img src="/hero.avif" alt="Hero" width="1200" height="600" fetchpriority="high">
Always set width and height to avoid layout shifts.
Improving Interaction to Next Paint (INP)
INP measures responsiveness. Long tasks block the main thread, delaying visual feedback. To improve INP:
- Break up long tasks: use
setTimeoutorscheduler.yieldto yield to the browser. - Optimize event handlers: debounce input, avoid heavy synchronous work.
- Reduce JavaScript: code-split, tree-shake, and defer non-critical scripts.
- Use web workers for CPU-intensive tasks.
- Avoid large DOM updates: batch DOM changes and use requestAnimationFrame.
Example: yield to the main thread during a long loop:
async function processItems(items) {
for (let i = 0; i < items.length; i++) {
// do work
if (i % 50 === 0) {
await new Promise(resolve => setTimeout(resolve, 0));
}
}
}
This keeps the page responsive during heavy processing.
Improving Cumulative Layout Shift (CLS)
CLS happens when elements move unexpectedly. Common causes: images without dimensions, ads, embeds, and web fonts.
- Always include width and height on images and videos.
- Reserve space for dynamic content (ads, embeds) with CSS
min-heightor aspect-ratio boxes. - Use
font-display: swapand preload fonts to avoid invisible text and layout shifts. - Avoid inserting content above existing content unless it's in response to user interaction.
Example: use aspect-ratio to reserve space:
.video-container {
aspect-ratio: 16 / 9;
width: 100%;
}
This prevents shifts when the video loads.
Monitor and Iterate
Performance is not a one-time fix. Set up continuous monitoring with real user metrics. Use dashboards to track LCP, INP, and CLS over time. After each change, verify with lab tools and check field data after a few days. Prioritize fixes that affect the most users.
FAQ
What are the current thresholds for Core Web Vitals?
LCP: good ≤2.5s, needs improvement 2.5–4.0s, poor >4.0s. INP: good ≤200ms, needs improvement 200–500ms, poor >500ms. CLS: good ≤0.1, needs improvement 0.1–0.25, poor >0.25.
How often should I measure Core Web Vitals?
Monitor field data continuously and run lab tests after each significant change. Check Search Console weekly for trends.
Can I improve Core Web Vitals without rebuilding my site?
Yes. Many improvements like image optimization, preloading, and CSS adjustments can be applied incrementally without a full rebuild.
Need to quickly compress images to improve LCP? Try our free Image Compressor to reduce file sizes without losing quality.