Last updated
What Are Core Web Vitals?
Core Web Vitals are Google's performance metrics used as SEO ranking factors. They measure loading performance (LCP), interactivity (INP), and visual stability (CLS). The Web Vitals Calculator helps analyze your current scores, understand what's causing poor performance, and estimate the impact of optimizations.
Core Web Vitals Thresholds
Metric Full Name Good Needs Work Poor
------ --------- ---- ---------- ----
LCP Largest Contentful Paint ≤ 2.5s 2.5–4.0s > 4.0s
INP Interaction to Next Paint ≤ 200ms 200–500ms > 500ms
CLS Cumulative Layout Shift ≤ 0.1 0.1–0.25 > 0.25
(FID was replaced by INP in March 2024)
LCP — Largest Contentful Paint
What it measures: Time until the largest visible content element loads
Common LCP elements:
- Hero images (most common)
- Large text blocks (H1 headings)
- Video poster images
- Background images loaded via CSS
Current score: 3.8s (Needs Improvement)
LCP breakdown:
Time to First Byte (TTFB): 0.8s
Resource load delay: 0.5s
Resource load time: 2.1s
Element render delay: 0.4s
Total LCP: 3.8s
Optimizations and estimated improvements:
Preload LCP image: -0.8s → 3.0s
Use CDN for images: -0.5s → 2.5s
Compress hero image (WebP): -0.3s → 2.2s
Improve server TTFB: -0.4s → 1.8s ✓ Good
HTML fix — preload LCP image:
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high">
<img src="/hero.webp" alt="Hero" fetchpriority="high">
INP — Interaction to Next Paint
What it measures: Latency of ALL interactions (click, tap, keyboard)
Replaces FID (which only measured the first interaction)
Current score: 380ms (Poor)
Common causes of poor INP:
- Long JavaScript tasks blocking the main thread
- Heavy event handlers
- Synchronous DOM updates
- Large React re-renders
Interaction breakdown:
Input delay: 120ms (main thread busy)
Processing time: 210ms (event handler execution)
Presentation delay: 50ms (rendering)
Total INP: 380ms
Optimizations:
Break up long tasks with scheduler.yield(): -150ms → 230ms
Debounce input handlers: -80ms → 150ms ✓ Good
Use web workers for heavy computation: -100ms → 130ms ✓ Good
Code fix — break up long tasks:
// BAD — blocks main thread
function heavyTask() {
for (let i = 0; i < 1000000; i++) { /* work */ }
}
// GOOD — yield to browser between chunks
async function heavyTask() {
for (let i = 0; i < 1000000; i++) {
if (i % 1000 === 0) await scheduler.yield();
/* work */
}
}
CLS — Cumulative Layout Shift
What it measures: Total unexpected layout movement during page load
Current score: 0.18 (Needs Improvement)
CLS contributors:
Images without dimensions: 0.08 (largest contributor)
Late-loading ads: 0.06
Web fonts causing FOUT: 0.04
Total CLS: 0.18
Optimizations:
Add width/height to all images: -0.08 → 0.10 (borderline)
Reserve space for ads: -0.06 → 0.04 ✓ Good
Use font-display: optional: -0.04 → 0.00 ✓ Good
HTML fix — always specify image dimensions:
<!-- BAD — causes layout shift when image loads -->
<img src="photo.jpg" alt="Photo">
<!-- GOOD — browser reserves space before image loads -->
<img src="photo.jpg" alt="Photo" width="800" height="600">
<!-- GOOD — aspect-ratio CSS -->
<img src="photo.jpg" alt="Photo" style="aspect-ratio: 4/3; width: 100%">
Impact on SEO Rankings
Google Page Experience signals:
✓ Core Web Vitals (LCP, INP, CLS)
✓ HTTPS
✓ Mobile-friendly
✓ No intrusive interstitials
Score improvement impact (estimated):
Before optimization:
LCP: 3.8s (Poor) → negative ranking signal
INP: 380ms (Poor) → negative ranking signal
CLS: 0.18 (Needs) → slight negative signal
After optimization:
LCP: 1.8s (Good) → positive ranking signal
INP: 130ms (Good) → positive ranking signal
CLS: 0.04 (Good) → positive ranking signal
E-commerce impact (research data):
100ms LCP improvement → ~1% conversion rate increase
0.1 CLS improvement → ~8% fewer abandoned sessions
Measuring Core Web Vitals
Lab measurement (development):
Google Lighthouse (Chrome DevTools)
PageSpeed Insights: pagespeed.web.dev
WebPageTest: webpagetest.org
Field measurement (real users):
Chrome User Experience Report (CrUX)
Google Search Console → Core Web Vitals report
web-vitals JavaScript library
// Measure with web-vitals library
import { onLCP, onINP, onCLS } from 'web-vitals';
onLCP(metric => console.log('LCP:', metric.value));
onINP(metric => console.log('INP:', metric.value));
onCLS(metric => console.log('CLS:', metric.value));
Quick Wins Checklist
- Add
fetchpriority="high"to the LCP image - Preload the LCP image with
<link rel="preload"> - Add explicit width and height to all images
- Convert images to WebP format
- Reserve space for ads and embeds with min-height
- Use
font-display: swaporoptionalfor web fonts - Break up JavaScript tasks longer than 50ms
- Defer non-critical JavaScript with
deferorasync