Introduction
Core Web Vitals are a set of specific metrics that Google considers essential for delivering a great user experience on the web. They measure three critical aspects: loading performance (Largest Contentful Paint), interactivity (Interaction to Next Paint), and visual stability (Cumulative Layout Shift).
Since Google uses these metrics as ranking signals, optimizing Core Web Vitals directly impacts both user satisfaction and search visibility. Poor scores mean users leave before your page loads, while good scores correlate with lower bounce rates and higher conversions.
This guide walks you through each metric, how to measure it, and concrete optimization strategies you can implement today.
Key Concepts
Largest Contentful Paint (LCP)
LCP measures how long it takes for the largest visible content element to render. Target: under 2.5 seconds. The largest element is typically a hero image, heading, or video poster.
new PerformanceObserver((list) => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('LCP:', lastEntry.startTime, lastEntry.element);
}).observe({ type: 'largest-contentful-paint', buffered: true });
Interaction to Next Paint (INP)
INP replaced FID in March 2024. It measures the latency of all interactions throughout the page lifecycle, reporting the worst interaction. Target: under 200ms.
new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
console.log('Long task:', entry.duration, 'ms');
});
}).observe({ type: 'longtask', buffered: true });
Cumulative Layout Shift (CLS)
CLS measures unexpected layout shifts during the page's lifetime. Target: under 0.1. Layout shifts happen when visible elements move without user interaction — images without dimensions, dynamically injected content, or web fonts causing FOUT.
Practical Examples
1. Optimizing LCP with Preload
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high">
<img src="/hero.webp" alt="Hero" fetchpriority="high" width="1200" height="600">
2. Reducing CLS with Aspect Ratios
.hero-image {
aspect-ratio: 16 / 9;
width: 100%;
object-fit: cover;
}
.ad-slot {
min-height: 250px;
contain: layout;
}
3. Improving INP with Yielding
async function processItems(items) {
for (const item of items) {
processItem(item);
if (navigator.scheduling?.isInputPending()) {
await scheduler.yield();
}
}
}
4. Font Loading Without CLS
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: optional;
}
Best Practices
- ✅ Always set explicit width and height on images and videos to prevent CLS
- ✅ Preload your LCP element (hero image, font, or critical resource)
- ✅ Use fetchpriority='high' on the LCP image and 'low' on below-fold images
- ✅ Break up long JavaScript tasks into smaller chunks to improve INP
- ✅ Serve images in modern formats (WebP/AVIF) with proper sizing
- ❌ Don't lazy-load above-the-fold images — it hurts LCP
- ❌ Don't inject content above existing content without reserving space
Common Pitfalls
- 🚫 Measuring only in lab tools — field data (CrUX) is what Google uses for rankings
- 🚫 Ignoring third-party scripts — ads, analytics, and chat widgets often cause the worst layout shifts
- 🚫 Over-lazy-loading — lazy loading everything delays LCP
- 🚫 Using placeholder fonts with very different metrics — causes significant CLS when the real font loads
Related Guides
- → Image Optimization Complete Guide
- → Font Loading Strategies
- → Performance Monitoring Setup
- → Page Speed & SEO Impact