Learning Hub

Core Web Vitals Deep Dive

Understand what each metric measures, what causes poor scores, and how to fix them with production-ready code examples.

Threshold: ≤ 2.5s is Good, > 4.0s is Poor

✗ Common Causes

  • Slow server response time (TTFB > 600ms)
  • Render-blocking CSS or JavaScript
  • Unoptimised hero images (wrong format, no srcset)
  • Missing resource hints (preload, preconnect)
  • Client-side rendering with no SSR/SSG

✓ How to Fix

  • Preload the LCP image with <link rel="preload"> and fetchpriority="high"
  • Serve images in WebP/AVIF with responsive srcset
  • Inline critical CSS and defer non-critical stylesheets
  • Use a CDN for static assets (Vercel Edge, Cloudflare)
  • Enable stale-while-revalidate caching on HTML

LCP Optimisation — Before vs After

✗ Before
slow-page.html
<!-- No preload, no priority, huge PNG -->
<img src="/hero-banner.png" alt="Hero">

<!-- Render-blocking stylesheet -->
<link rel="stylesheet" href="/heavy-theme.css">
✓ After
optimised-page.html
<!-- Preload LCP image with priority -->
<link rel="preload" as="image" href="/hero.webp"
  fetchpriority="high"
  imagesrcset="/hero-480.webp 480w,
               /hero-800.webp 800w,
               /hero-1200.webp 1200w"
  imagesizes="100vw" />

<img src="/hero.webp" alt="Hero"
  width="1200" height="600"
  fetchpriority="high" decoding="async" />

<!-- Defer non-critical CSS -->
<link rel="preload" href="/theme.css"
  as="style" onload="this.rel='stylesheet'" />

Impact: LCP improved from ~4.2s to ~1.8s by preloading the hero image, serving WebP, and deferring non-critical CSS.

Measurement Tools