What You Will Learn
- How the CLS score is calculated using impact fraction and distance fraction
- Why images without width/height attributes are the most common CLS cause
- How to reserve space for ads, embeds, and iframes to prevent unexpected shifts
- How web font loading causes FOUT/FOIT and three strategies to prevent it
- How to handle dynamically injected content (banners, notifications) without causing CLS
- Which CSS animation properties cause layout shifts and how to avoid them
- How to use Chrome DevTools Layout Shift Regions to find CLS sources
What is Cumulative Layout Shift
Cumulative Layout Shift (CLS) measures visual stability — how much page content unexpectedly moves during loading or use. A high CLS score causes accidental taps on wrong elements and significant user frustration. Unlike LCP and INP, CLS is a dimensionless score calculated from the geometry of unexpected layout shifts, not a time measurement.
A score of 0 means no unexpected shifts occurred. Google classifies scores of 0.1 or below as Good, 0.1–0.25 as Needs Improvement, and above 0.25 as Poor. The ranking signal uses the 75th percentile of real user sessions.
Good CLS
Target for 75th percentile of page visits
Poor CLS
Above this is a significant UX problem
Top cause
Of CLS issues are image-related (no dimensions)
How the CLS Score is Calculated
Each layout shift is scored as: layout shift score = impact fraction x distance fraction. The impact fraction is the fraction of the viewport area affected (before + after position union). The distance fraction is how far the element moved relative to the viewport's largest dimension.
Google uses the maximum "session window" — the highest-scoring 5-second burst of layout shifts — as the reported CLS value. Layout shifts within 500ms of a user interaction (click, tap, keypress) are excluded because they are expected, intentional shifts.
Accordion expansions, "read more" reveals, and any content change within 500ms of a user interaction are excluded. Only unexpected shifts — those that happen without a user trigger — are penalised.
Fix 1 — Images Without Dimensions
The most common and highest-impact CLS fix: add explicit width and height attributes to every img and video element. Without declared dimensions, the browser allocates zero space initially. When the image loads, it pushes surrounding content down — creating a layout shift.
Add width and height matching the image's intrinsic dimensions. Use CSS to keep images responsive:
<!-- Before: causes shift -->
<img src="hero.jpg" alt="Hero">
<!-- After: reserves space -->
<img src="hero.jpg" alt="Hero" width="1200" height="600">
/* CSS: keeps images fluid */
img { max-width: 100%; height: auto; }
Modern browsers use declared width and height to calculate the aspect ratio before the image loads, reserving the exact space needed. This eliminates the shift entirely.
For CMS-generated or user-uploaded images where you cannot add explicit dimensions, use CSS aspect-ratio:
.article-image {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
}
Fix 2 — Ads, Embeds, and Iframes
Ads loaded asynchronously are one of the largest CLS contributors on commercial sites. Ad slots inject content after initial layout — without reserved space, the ad pushes surrounding content down when it loads.
.ad-slot {
min-height: 250px; /* IAB medium rectangle */
background: var(--g50); /* Optional placeholder */
}
For leaderboards (728x90), reserve min-height: 90px. For sidebar rectangles (300x250), reserve 250px. This ensures content below does not shift if a smaller ad loads.
<!-- Fixed-size iframe -->
<iframe src="..." width="560" height="315"
title="Video" loading="lazy"></iframe>
<!-- Responsive iframe -->
<div style="aspect-ratio: 16/9; width: 100%;">
<iframe src="..."
style="width:100%;height:100%;border:0;"></iframe>
</div>
Fix 3 — Web Font Layout Shifts
Web fonts cause CLS when the fallback font (used while the web font loads) has different metrics from the intended font. When the web font loads and replaces the fallback, the text reflows — causing a layout shift called FOUT (Flash of Unstyled Text).
@font-face {
font-family: 'Inter';
src: url('/fonts/Inter-Regular.woff2') format('woff2');
font-display: optional; /* No swap = no CLS */
}
font-display: optional gives the web font a very short loading window. If not loaded, browser uses the fallback for the entire page visit with no swap. Returning visitors with the font cached see zero delay.
@font-face {
font-family: 'Inter Fallback';
src: local('Arial');
size-adjust: 94%;
ascent-override: 92%;
descent-override: 24%;
}
body { font-family: 'Inter', 'Inter Fallback', sans-serif; }
This makes the fallback font occupy the same space as Inter, making the swap visually imperceptible even with font-display: swap.
Fix 4 — Dynamic Content Injection
Cookie consent banners, newsletter bars, notification popups, and promotional banners injected above content after load are major CLS sources on publisher and e-commerce sites.
.cookie-banner {
position: fixed;
bottom: 0; /* Expands into empty space */
left: 0;
right: 0;
z-index: 100;
/* Zero CLS — does not shift existing content */
}
<!-- Reserve space in initial HTML for known banner -->
<div class="banner-slot" style="min-height:56px;"
aria-hidden="true"></div>
Fix 5 — CSS Animations That Cause Layout Shifts
Animating layout properties (top, left, width, height, margin, padding) forces layout recalculation and causes shifts. Use only compositor-only properties (transform, opacity) for animations.
| Property | Triggers Layout | Alternative |
|---|---|---|
| top, left, right, bottom | Yes — CLS risk | transform: translateX() / translateY() |
| width, height | Yes — CLS risk | transform: scale() |
| margin, padding | Yes — CLS risk | transform: translate() |
| transform | No — compositor | Always preferred |
| opacity | No — compositor | Always preferred |
/* Bad: triggers layout */
@keyframes slideIn {
from { left: -100px; }
to { left: 0; }
}
/* Good: compositor-only, no CLS */
@keyframes slideIn {
from { transform: translateX(-100px); }
to { transform: translateX(0); }
}
Authentic Sources
Official CLS definition, score calculation, and thresholds.
font-display values and size-adjust technique for CLS prevention.
Chrome DevTools Layout Shift Regions and Performance panel usage.