PureTools

Core Web Vitals: LCP, INP, CLS Explained

PureTools Team· 8 min read
Core Web Vitals: LCP, INP, CLS Explained

Core Web Vitals: What Google Measures

Google uses three metrics to judge your page's user experience. They affect search rankings, and more importantly, they affect whether users stay on your page or bounce.

The Three Metrics

MetricMeasuresGoodNeeds WorkPoor
LCPLoading speed (largest content paint)≤ 2.5s≤ 4.0s> 4.0s
INPResponsiveness (interaction to next paint)≤ 200ms≤ 500ms> 500ms
CLSVisual stability (cumulative layout shift)≤ 0.1≤ 0.25> 0.25

LCP — Largest Contentful Paint

How long until the largest visible element (hero image, heading, video) is fully rendered. Common LCP elements:

  • Hero images
  • Large text blocks (h1)
  • Video poster images
  • Background images via CSS

How to improve LCP:

<!-- Preload your LCP image -->
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high" />

<!-- Use modern formats -->
<picture>
  <source srcset="hero.avif" type="image/avif" />
  <source srcset="hero.webp" type="image/webp" />
  <img src="hero.jpg" alt="Hero" width="1200" height="630" fetchpriority="high" />
</picture>
  • Serve images in WebP/AVIF format (40-60% smaller)
  • Use fetchpriority="high" on the LCP element
  • Don't lazy-load above-the-fold images
  • Use a CDN for static assets
  • Minimize render-blocking CSS and JS

INP — Interaction to Next Paint

Measures how quickly the page responds to user interactions (clicks, taps, key presses). INP replaced FID (First Input Delay) in March 2024.

How to improve INP:

// Break up long tasks
// BAD: blocks the main thread for 200ms
function processData(items) {
  items.forEach(item => heavyComputation(item));
}

// GOOD: yield to the browser between chunks
async function processData(items) {
  for (let i = 0; i < items.length; i++) {
    heavyComputation(items[i]);
    if (i % 100 === 0) {
      await new Promise(r => setTimeout(r, 0)); // yield
    }
  }
}
  • Keep JavaScript tasks under 50ms
  • Use requestAnimationFrame for visual updates
  • Debounce rapid interactions (scroll, resize)
  • Move heavy computation to Web Workers
  • Reduce third-party script impact

CLS — Cumulative Layout Shift

Measures unexpected layout shifts — when elements move around as the page loads. The worst offenders:

  • Images without dimensions (browser doesn't know the size until loaded)
  • Ads/embeds injected dynamically
  • Web fonts causing FOUT (flash of unstyled text)
  • Dynamic content inserted above existing content

How to improve CLS:

<!-- Always set width and height on images -->
<img src="photo.jpg" width="800" height="600" alt="Photo" />

<!-- Reserve space for ads -->
<div style="min-height: 250px;">
  <!-- ad slot -->
</div>

<!-- Preload fonts to prevent layout shift -->
<link rel="preload" as="font" href="/fonts/inter.woff2"
      type="font/woff2" crossorigin />
/* CSS: prevent font swap layout shift */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2') format('woff2');
  font-display: swap; /* or 'optional' for no shift at all */
}

Measuring Tools

ToolTypeWhat It Tells You
PageSpeed InsightsLab + FieldReal user data + lab simulation
Chrome DevTools (Lighthouse)LabDetailed performance audit
Web Vitals ExtensionReal-timeLive metrics as you browse
Search ConsoleFieldReal user data aggregated

Optimize your images: Image Converter — convert to WebP/AVIF for smaller files and better LCP scores.