Concept · Building apps
Core Web Vitals
LCP, INP and CLS: loading, responsiveness and visual stability, measured on real users at the 75th percentile.
Core Web Vitals are three metrics Google uses to describe how a page feels to the people using it. They're measured in real users' browsers, and a page passes when it hits the target for at least 75% of visits.
| Metric | Measures | Good | Poor |
|---|---|---|---|
| LCP — Largest Contentful Paint | When the main content (biggest image or text block) appears | ≤ 2.5 s | > 4 s |
| INP — Interaction to Next Paint | Delay from a click, tap or key press to the next frame | ≤ 200 ms | > 500 ms |
| CLS — Cumulative Layout Shift | How much visible content jumps around unexpectedly | ≤ 0.1 | > 0.25 |
LCP: show the main thing sooner
LCP time breaks into four parts: server response (TTFB), the delay before the browser discovers the resource, the download, and the render. Common fixes:
- Make the hero image discoverable in the HTML. Don't lazy-load it, and add
fetchpriority="high". - Serve modern, correctly sized images (AVIF/WebP with
srcset). - Cut render-blocking CSS and JS on the critical path.
- Use server rendering or a CDN for a fast first byte. See rendering strategies.
INP: keep the main thread free
An interaction can't produce a frame while a long task is running. INP reports roughly the slowest interaction on the visit, so one heavy click handler is enough to fail it.
- Break up long tasks, and yield to the browser with
scheduler.yield()orawait new Promise(r => setTimeout(r)). - Do the visible update first and defer the rest, using
startTransitionin React. - Ship less JavaScript and do less hydration. See code splitting.
CLS: reserve space
- Set
width/heightoraspect-ratioon images, videos and embeds. - Reserve space for ads, banners and late-loading content instead of inserting it above what the user is reading.
- Use
font-display: optionalor matched fallback metrics so web fonts don't reflow text. - Animate with
transform, nottoporheight.
Lab data vs field data
Lighthouse is lab data: one simulated load on one simulated device. It's good for debugging but not the score that counts. Field data from real users, collected by the Chrome UX Report or your own RUM with the web-vitals library, is what's assessed. Because the threshold is the 75th percentile, you're tuning for slow phones and slow networks, much like the server-side lesson that tail latency matters more than the average.