Difficulty: Advanced
What are Core Web Vitals? How does CSS affect them?
Core Web Vitals are Google's key metrics for user experience (affect SEO ranking):
1. LCP (Largest Contentful Paint): time for largest visible element to render. Target: < 2.5s 2. CLS (Cumulative Layout Shift): visual stability (elements jumping around). Target: < 0.1 3. INP (Interaction to Next Paint, replaced FID): responsiveness to user input. Target: < 200ms
CSS impact on Web Vitals: - LCP: render-blocking CSS, large images, custom fonts - CLS: images without dimensions, dynamically injected content, web fonts causing FOIT/FOUT - INP: long-running CSS animations, expensive selectors
/* 1. Always set image dimensions */
<img src="photo.jpg" width="800" height="600"
alt="Photo" />
/* Or use aspect-ratio in CSS */
img {
aspect-ratio: 4 / 3;
width: 100%;
height: auto;
}
/* 2. Reserve space for dynamic content */
.ad-slot {
min-height: 250px; /* reserve space before ad loads */
}
/* 3. Prevent font swap layout shift */
@font-face {
font-family: 'Inter';
src: url('inter.woff2') format('woff2');
font-display: swap;
/* optional: prevents shift entirely but may flash */
/* swap: shows fallback then swaps (may shift) */
}
/* 4. Avoid inserting content above existing content */
/* BAD: banner pushes everything down */
.notification-bar {
/* If injected at top, shifts all content */
}
/* GOOD: use transform to slide in */
.notification-bar {
transform: translateY(-100%);
transition: transform 0.3s;
}
.notification-bar.visible {
transform: translateY(0);
}
CLS is caused by elements that change size or position after initial render. Always reserve space for images, ads, and dynamic content.
<!-- 1. Preload critical resources -->
<link rel="preload" as="image"
href="hero-image.jpg" />
<link rel="preload" as="font"
href="inter.woff2"
type="font/woff2" crossorigin />
<!-- 2. Inline critical CSS -->
<style>
/* Only above-the-fold styles */
.hero { min-height: 100vh; }
.nav { height: 64px; }
</style>
<link rel="stylesheet" href="full.css"
media="print" onload="this.media='all'" />
<!-- Loads full CSS without blocking render -->
<!-- 3. Optimize LCP image -->
<img src="hero.jpg"
srcset="hero-400.jpg 400w,
hero-800.jpg 800w,
hero-1200.jpg 1200w"
sizes="100vw"
loading="eager"
fetchpriority="high"
decoding="async"
alt="Hero" />
<!-- 4. Avoid lazy loading above-the-fold images -->
<!-- loading="lazy" delays LCP for hero images -->
LCP measures when the largest visible element renders. Preload critical resources, inline critical CSS, and never lazy-load above-the-fold images.
/* 1. Minimize render-blocking CSS */
/* Split CSS: critical inline + rest async */
/* 2. Reduce unused CSS */
/* Use PurgeCSS or Tailwind's built-in purging */
/* 3. Avoid expensive selectors */
/* BAD */
*:not(.special) { } /* matches almost everything */
.wrapper > div > ul > li > a { } /* deep nesting */
/* GOOD */
.nav-link { } /* single class, fast */
/* 4. Use font-display */
@font-face {
font-display: optional;
/* optional: uses fallback if font takes too long */
/* Best for CLS, may not show custom font */
}
/* 5. Use contain for component isolation */
.card {
contain: content;
/* Isolates layout/paint calculations */
}
/* 6. Use content-visibility for long pages */
.section {
content-visibility: auto;
contain-intrinsic-size: auto 500px;
/* Browser skips rendering until scrolled into view */
}
content-visibility: auto can dramatically improve initial page load by skipping rendering of offscreen content. contain: content isolates recalculation scope.
Core Web Vitals, CLS, LCP, FID, INP, Performance, SEO