Google's definitive guide to measuring and optimizing LCP, CLS, and INP. Essential reading. Read →
| Metric | Measures | Good | Poor |
|---|---|---|---|
| LCP (Largest Contentful Paint) | Load performance — how fast main content appears | <2.5s | >4.0s |
| INP (Interaction to Next Paint) | Responsiveness — delay after user interaction | <200ms | >500ms |
| CLS (Cumulative Layout Shift) | Visual stability — do elements jump while loading? | <0.1 | >0.25 |
# Tools:
1. PageSpeed Insights: https://pagespeed.web.dev/
2. Chrome DevTools → Lighthouse tab
3. web-vitals npm package (real user data)
npm install web-vitals
import { onCLS, onINP, onLCP } from 'web-vitals';
onCLS(m => sendToAnalytics('CLS', m.value));
onINP(m => sendToAnalytics('INP', m.value));
onLCP(m => sendToAnalytics('LCP', m.value));
<!-- Preload the LCP image — fetched immediately, not discovered late -->
<link rel="preload" as="image" href="/hero.webp" />
<!-- fetchpriority on the LCP element -->
<img src="/hero.webp" fetchpriority="high" alt="Hero" />
<!-- Use modern formats (WebP/AVIF: 30-50% smaller) -->
<picture>
<source srcset="/hero.avif" type="image/avif" />
<source srcset="/hero.webp" type="image/webp" />
<img src="/hero.jpg" alt="Hero" />
</picture>
// Server-side LCP improvements:
// - Redis caching reduces TTFB
// - CloudFront CDN reduces network latency
// - HTTP/2 push or preload hints
<!-- Always set explicit dimensions on images -->
<img src="/photo.jpg" width="800" height="600" alt="..." />
/* Reserve space for dynamic content */
.ad-container { min-height: 250px; }
/* Font loading: prevent FOUT causing layout shift */
font-display: optional; /* don't show fallback font */
/* Or preload fonts */
<link rel="preload" href="/fonts/inter.woff2" as="font" crossorigin />