Skip to content
Performance

Core Web Vitals Optimization Guide

Master Core Web Vitals (LCP, INP, CLS) to improve user experience and search rankings.

stellae.design

8 min read

Introduction

Core Web Vitals are a set of specific metrics that Google considers essential for delivering a great user experience on the web. They measure three critical aspects: loading performance (Largest Contentful Paint), interactivity (Interaction to Next Paint), and visual stability (Cumulative Layout Shift).

Since Google uses these metrics as ranking signals, optimizing Core Web Vitals directly impacts both user satisfaction and search visibility. Poor scores mean users leave before your page loads, while good scores correlate with lower bounce rates and higher conversions.

This guide walks you through each metric, how to measure it, and concrete optimization strategies you can implement today.


Key Concepts

Largest Contentful Paint (LCP)

LCP measures how long it takes for the largest visible content element to render. Target: under 2.5 seconds. The largest element is typically a hero image, heading, or video poster.

javascript
new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lastEntry = entries[entries.length - 1];
  console.log('LCP:', lastEntry.startTime, lastEntry.element);
}).observe({ type: 'largest-contentful-paint', buffered: true });

Interaction to Next Paint (INP)

INP replaced FID in March 2024. It measures the latency of all interactions throughout the page lifecycle, reporting the worst interaction. Target: under 200ms.

javascript
new PerformanceObserver((list) => {
  list.getEntries().forEach((entry) => {
    console.log('Long task:', entry.duration, 'ms');
  });
}).observe({ type: 'longtask', buffered: true });

Cumulative Layout Shift (CLS)

CLS measures unexpected layout shifts during the page's lifetime. Target: under 0.1. Layout shifts happen when visible elements move without user interaction — images without dimensions, dynamically injected content, or web fonts causing FOUT.


Practical Examples

1. Optimizing LCP with Preload

html
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high">
<img src="/hero.webp" alt="Hero" fetchpriority="high" width="1200" height="600">

2. Reducing CLS with Aspect Ratios

css
.hero-image {
  aspect-ratio: 16 / 9;
  width: 100%;
  object-fit: cover;
}
.ad-slot {
  min-height: 250px;
  contain: layout;
}

3. Improving INP with Yielding

javascript
async function processItems(items) {
  for (const item of items) {
    processItem(item);
    if (navigator.scheduling?.isInputPending()) {
      await scheduler.yield();
    }
  }
}

4. Font Loading Without CLS

css
@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: optional;
}

Best Practices

  • ✅ Always set explicit width and height on images and videos to prevent CLS
  • ✅ Preload your LCP element (hero image, font, or critical resource)
  • ✅ Use fetchpriority='high' on the LCP image and 'low' on below-fold images
  • ✅ Break up long JavaScript tasks into smaller chunks to improve INP
  • ✅ Serve images in modern formats (WebP/AVIF) with proper sizing
  • ❌ Don't lazy-load above-the-fold images — it hurts LCP
  • ❌ Don't inject content above existing content without reserving space

Common Pitfalls

  • 🚫 Measuring only in lab tools — field data (CrUX) is what Google uses for rankings
  • 🚫 Ignoring third-party scripts — ads, analytics, and chat widgets often cause the worst layout shifts
  • 🚫 Over-lazy-loading — lazy loading everything delays LCP
  • 🚫 Using placeholder fonts with very different metrics — causes significant CLS when the real font loads

Performanceperformance

Was this article helpful?