ESC
Type to search guides, tutorials, and reference documentation.
Verified by Garnet Grid

Core Web Vitals Optimization

Optimize the three Core Web Vitals that Google uses for search ranking and user experience. Covers Largest Contentful Paint, Cumulative Layout Shift, Interaction to Next Paint, measurement tools, and the performance engineering patterns that deliver fast, stable, responsive pages.

Core Web Vitals are Google’s three metrics for measuring real user experience. They directly impact search rankings and, more importantly, conversion rates. Every 100ms of delay loses 1% of revenue. Every unexpected layout shift loses user trust. CWV optimization is not optional — it is the price of being competitive on the web.


The Three Metrics

LCP (Largest Contentful Paint): < 2.5 seconds
  "How fast does the main content appear?"
  Measures: Largest image, video, or text block visible in viewport
  
INP (Interaction to Next Paint): < 200ms
  "How responsive is the page to user input?"
  Measures: Time from click/tap to visual response

CLS (Cumulative Layout Shift): < 0.1
  "How stable is the layout?"
  Measures: Unexpected movements of visible elements

LCP Optimization

<!-- Preload critical resources -->
<link rel="preload" href="/hero-image.webp" as="image" fetchpriority="high">
<link rel="preload" href="/fonts/inter-var.woff2" as="font" crossorigin>

<!-- Inline critical CSS -->
<style>
  /* Only above-the-fold styles */
  .hero { min-height: 60vh; display: flex; align-items: center; }
  .hero-image { width: 100%; height: auto; aspect-ratio: 16/9; }
</style>

<!-- Defer non-critical CSS -->
<link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'">

<!-- Responsive images with proper sizing -->
<img 
  src="/hero-800.webp" 
  srcset="/hero-400.webp 400w, /hero-800.webp 800w, /hero-1200.webp 1200w"
  sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
  alt="Hero image"
  width="1200" height="675"
  loading="eager"
  fetchpriority="high"
  decoding="async"
>
LCP Checklist:
  ☐ Hero image preloaded with fetchpriority="high"
  ☐ Critical CSS inlined (< 14KB)
  ☐ Fonts preloaded or use font-display: swap
  ☐ Server response < 200ms (TTFB)
  ☐ Images in WebP/AVIF format
  ☐ CDN for static assets
  ☐ No render-blocking JavaScript

CLS Optimization

/* Always set dimensions on media */
img, video {
  width: 100%;
  height: auto;
  aspect-ratio: attr(width) / attr(height);
}

/* Reserve space for dynamic content */
.ad-slot {
  min-height: 250px;  /* Reserve ad space */
}

.skeleton {
  min-height: 200px;  /* Reserve skeleton space */
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}

/* Prevent font swap layout shift */
@font-face {
  font-family: 'Inter';
  font-display: optional;  /* Don't swap if font loads late */
  src: url('/fonts/inter.woff2') format('woff2');
}
CLS Checklist:
  ☐ All images have width/height or aspect-ratio
  ☐ Ads/embeds have reserved space
  ☐ No dynamically injected content above fold
  ☐ font-display: optional or swap with matching fallback
  ☐ No late-loading CSS that changes layout

INP Optimization

// Break up long tasks (> 50ms) to stay responsive
async function processLargeDataset(items) {
  const CHUNK_SIZE = 100;
  
  for (let i = 0; i < items.length; i += CHUNK_SIZE) {
    const chunk = items.slice(i, i + CHUNK_SIZE);
    processChunk(chunk);
    
    // Yield to browser between chunks
    await new Promise(resolve => setTimeout(resolve, 0));
  }
}

// Use requestIdleCallback for non-urgent work
requestIdleCallback((deadline) => {
  while (deadline.timeRemaining() > 0) {
    doNonUrgentWork();
  }
});

// Debounce expensive event handlers
function debounce(fn, delay = 150) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
}

Anti-Patterns

Anti-PatternConsequenceFix
No image dimensionsCLS from images loadingAlways set width/height/aspect-ratio
Render-blocking JS in headLCP delayeddefer/async or move to body end
Synchronous third-party scriptsINP blocked by external codeLazy load, web workers
No CDNHigh TTFB globallyEdge CDN for static+dynamic
Lab-only testingMisses real user experienceReal User Monitoring (RUM)

Core Web Vitals are the bridge between engineering performance and business performance. Every millisecond you save converts directly into revenue, engagement, and search visibility.

Jakub Dimitri Rezayev
Jakub Dimitri Rezayev
Founder & Chief Architect • Garnet Grid Consulting

Jakub holds an M.S. in Customer Intelligence & Analytics and a B.S. in Finance & Computer Science from Pace University. With deep expertise spanning D365 F&O, Azure, Power BI, and AI/ML systems, he architects enterprise solutions that bridge legacy systems and modern technology — and has led multi-million dollar ERP implementations for Fortune 500 supply chains.

View Full Profile →