What is Core Web Vitals?
Core Web Vitals are Google's three standardized metrics that measure real-user page loading, interactivity, and visual stability.
What Are Core Web Vitals?
Core Web Vitals are three specific metrics Google uses to measure real user experience: Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS). Google announced them in May 2020, made them a ranking signal in June 2021, and swapped FID for INP in March 2024. The thresholds are LCP ≤ 2.5 seconds, INP ≤ 200 milliseconds, and CLS ≤ 0.1.
Here's what matters: these are field metrics from actual Chrome users via the Chrome User Experience Report (CrUX). Your Lighthouse lab scores don't count for ranking. We've optimized 50+ client sites, and passing all three thresholds consistently moves the needle on mobile rankings.
How it works
Core Web Vitals come from real user sessions, not lab tests. Google pulls CrUX data at the 75th percentile over a rolling 28-day window. That p75 number determines if you're "good," "needs improvement," or "poor."
LCP (Largest Contentful Paint): When the biggest visible thing on your page finishes rendering. Usually your hero image or main heading block. Starts counting at navigation. Gets wrecked by unoptimized images, render-blocking CSS, and slow TTFB.
INP (Interaction to Next Paint): Latency from user interaction to the next paint. Looks at every click, tap, and keypress during the visit and reports the worst one. Long JavaScript tasks, heavy event handlers, and layout thrashing kill this metric.
CLS (Cumulative Layout Shift): Unexpected page movement. Each shift gets scored by (impact fraction × distance fraction). Uses "session windows" — groups shifts into max 5-second windows with max 1-second gaps between them, reports the biggest window's total.
You can measure these in the field with CrUX, PageSpeed Insights, or the web-vitals library:
import { onLCP, onINP, onCLS } from 'web-vitals';
onLCP(console.log);
onINP(console.log);
onCLS(console.log);
Lighthouse can simulate LCP and CLS in lab conditions but can't measure INP — you need real user interactions for that.
When to use it
Core Web Vitals are a confirmed Google ranking signal. You can't ignore them if you care about organic traffic. But timing matters.
Fix CWV when:
- You're losing to competitors with similar content
- Your mobile CrUX data is "poor" or "needs improvement"
- You're launching or redesigning — fixing it at build time is 10x cheaper
- You're running paid campaigns — CWV affects your Google Ads landing page scores
Don't obsess over CWV when:
- Your content or topical authority is the real problem — CWV is a tiebreaker
- You're chasing Lighthouse 100 but your field data already passes — lab perfection is vanity
- You're breaking functionality to game the metrics — removing interactivity to lower INP is backwards
We default to Next.js with App Router or Astro because they give us strong CWV baselines out of the box. Most optimization time goes into image delivery (LCP) and wrangling third-party scripts (INP).
Core Web Vitals vs alternatives
CWV are the only performance metrics Google uses directly for ranking.
| Metric | What it measures | Ranking signal? | Source |
|---|---|---|---|
| LCP | Largest paint timing | Yes (CWV) | CrUX field data |
| INP | Interaction responsiveness | Yes (CWV) | CrUX field data |
| CLS | Visual stability | Yes (CWV) | CrUX field data |
| FID | First interaction delay | Deprecated March 2024 | Was CrUX |
| TTFB | Server response time | No (diagnostic) | Lab or field |
| FCP | First content paint | No (diagnostic) | Lab or field |
| Speed Index | Visual completeness over time | No (lab only) | Lighthouse |
| TBT | Total blocking time | No (lab proxy for INP) | Lighthouse |
TBT in Lighthouse is your best lab proxy for INP. If TBT is under 200ms, you're usually fine on INP in the field. Usually. Heavy third-party scripts that load after Lighthouse finishes can still blow up real-world INP.
Real-world example
We inherited an e-commerce site on Next.js 14 and Vercel with LCP at 4.8 seconds (p75, mobile) and CLS at 0.24. Three changes fixed it.
Switched product hero images to next/image with priority loading and AVIF format — LCP dropped to 2.1 seconds. Added explicit width and height to all ad slots and lazy-loaded embeds — CLS fell to 0.04. Deferred the chat widget's JavaScript with requestIdleCallback — INP went from 320ms to 140ms.
Six weeks later, once the CrUX data rolled over, mobile category pages gained an average of 4 positions in Google Search Console. Total engineering time: about 20 hours.