What is Cumulative Layout Shift?
Cumulative Layout Shift (CLS) is one of Google's Core Web Vitals metrics that measures the visual stability of a webpage. It quantifies how often users experience unexpected layout shifts--moments when visible elements on a page move position after the page has already started loading. Unlike loading metrics such as LCP or FID, CLS focuses on the visual experience of stability during page use.
Unexpected layout shifts can significantly disrupt user experience:
- Reading disruption: Text shifts while users are reading, causing them to lose their place
- Misclick frustration: Users attempt to click a button or link, but the element moves just as they click
- Form errors: Input fields shift, causing users to enter data in the wrong place
- E-commerce consequences: Users accidentally add wrong items to cart or submit unintended orders
- Trust erosion: Shifting pages feel broken, unprofessional, and untrustworthy
CLS addresses a fundamental question: Does the page feel stable and predictable, or does content jump around unexpectedly?
Why CLS Matters for Your Website
CLS has become a critical metric for several reasons. First, it is a confirmed Google ranking factor and directly impacts search rankings, particularly on mobile devices where visual stability is paramount for user experience. Second, stable pages feel professional and polished, while shifting pages frustrate users and increase bounce rates--studies consistently show that visual stability affects conversion rates, with users being less likely to complete actions on unstable pages. Third, users with motor impairments or those using assistive technologies are disproportionately affected by unexpected layout changes, making CLS an important accessibility consideration alongside a broader web accessibility strategy.
CLS Score Thresholds
0.1
Good Score (or less)
0.10-0.25
Needs Improvement
>0.25
Poor Score
Understanding the CLS Scoring System
How CLS is Calculated
CLS is calculated using a formula that considers both how much content moves and how far it moves:
CLS Score = Impact Fraction × Distance Fraction
-
Impact Fraction: Measures how much of the viewport area is affected by the unstable element. It combines the visible area of the element in its previous and current positions, expressed as a fraction of the total viewport.
-
Distance Fraction: Measures how far the unstable element has moved relative to the viewport. It's the greatest horizontal or vertical distance any unstable element has moved, divided by the viewport's largest dimension.
Session Windows Explained
CLS uses a session window approach rather than summing all individual shifts. This prevents a single long page session from accumulating an unfair CLS score by recognizing that users may pause between interactions. A session window is a sequence of one or more layout shifts occurring in rapid succession, where each shift must occur within 1 second of the previous shift, and the maximum window duration is 5 seconds. If more than 1 second passes between shifts, a new window begins.
Example scenario: A user visits a news article that loads an ad banner after 2 seconds, causing a small shift. Then, 0.5 seconds later, a related article widget loads, causing another shift. These two shifts form a single session window. The CLS for this window is the sum of both shifts. If another shift occurs 3 seconds later, it starts a new window, and the overall page CLS becomes the largest single window's score rather than the cumulative total of all shifts.
This approach ensures fair scoring for pages with legitimate multi-stage loading patterns while still penalizing pages with frequent, disruptive shifts.
Common Causes of Cumulative Layout Shift
Understanding what causes layout shifts is the first step to fixing them. The most common culprits include:
1. Images Without Dimensions
Images without explicit width and height attributes are the leading cause of poor CLS scores. When browsers don't know an image's dimensions in advance, they can't reserve space for it, causing content below to shift once the image loads. A hero image that loads slowly can push an entire article's worth of content down, frustrating users who have already started reading.
2. Ads, Embeds, and Iframes
Dynamic content like advertisements, YouTube embeds, social media widgets, and iframes frequently cause layout shifts because they load asynchronously after main content, their dimensions are often unknown until they load, and they may dynamically resize based on content or viewport. Ad networks may inject content at unpredictable times, making this a particularly challenging issue for ad-supported sites. Using proper ad placement strategies with fixed dimensions can mitigate these shifts.
3. Dynamically Injected Content
Any content added to the DOM after initial render can cause shifts. This includes loading indicators that are replaced by content, banner notifications or cookie consent dialogs, chat widgets that expand or contract, lazy-loaded content that appears as users scroll, and AJAX results that populate search or filter results. Progressive content loading should always reserve space for expected content.
4. Web Fonts
Web fonts can cause layout shifts through two mechanisms. FOIT (Flash of Invisible Text) occurs when text is invisible until the font loads, then suddenly appears, shifting content. FOUT (Flash of Unstyled Text) happens when a fallback font is replaced by the web font, which may have different character dimensions. Even with proper loading, different fonts have different character widths and line heights that can cause subtle shifts.
5. CSS Animations and Transitions
Improperly implemented CSS animations can trigger layout shifts when animating properties that affect layout (width, height, top, left, margin, padding), when animations cause reflow of surrounding elements, or when transitions aren't smooth or expected. Always use CSS transforms for animations as part of a comprehensive performance optimization strategy.
Chrome DevTools
Record performance traces to identify layout shifts with animated before/after visualization and detailed insights
Lighthouse
Automated auditing with specific CLS score and actionable recommendations for fixes
PageSpeed Insights
Shows both lab data (Lighthouse) and real-user data (CrUX) for comprehensive analysis
web-vitals Library
JavaScript library for collecting real-user CLS measurements in production environments
Optimizing CLS: Best Practices
1. Always Include Image Dimensions
<!-- Always specify width and height -->
<img src="hero-image.jpg" width="800" height="600" alt="Description">
<!-- For responsive images -->
<img
src="hero-800.jpg"
srcset="hero-400.jpg 400w, hero-800.jpg 800w"
sizes="(max-width: 600px) 400px, 800px"
width="800"
height="600"
alt="Description"
>
Modern browsers calculate aspect-ratio from width/height attributes automatically, reserving space before images load. This is the single most impactful fix for CLS. Pair this with proper image optimization techniques for maximum effect.
2. Reserve Space for Ads and Embeds
/* Fixed size container for predictable dimensions */
.ad-container {
min-height: 250px;
width: 100%;
aspect-ratio: 300 / 250;
}
/* Responsive embed container */
.embed-container {
aspect-ratio: 16 / 9;
width: 100%;
}
Use CSS aspect-ratio or min-height to ensure containers have dimensions even before content loads. For variable-sized ads, use a skeleton layout or minimum viable placeholder.
3. Preload Critical Web Fonts
<!-- Preload web fonts for faster loading -->
<link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin>
<style>
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-var.woff2') format('woff2');
font-display: swap;
}
</style>
The font-display: swap value shows fallback font immediately and swaps to the web font when loaded, which is recommended for balancing visual stability with performance.
4. Skeleton Loading States
.skeleton {
background: linear-gradient(
90deg,
#f0f0f0 25%,
#e0e0e0 50%,
#f0f0f0 75%
);
background-size: 200% 100%;
animation: loading 1.5s infinite;
min-height: 200px;
}
Skeleton placeholders maintain layout stability while content loads asynchronously, preventing jarring shifts when content appears.
5. Use CSS Transforms for Animations
/* Good - transform-based animations don't trigger reflow */
.animated-element {
width: 100px;
height: 100px;
transform: scale(1);
transition: transform 0.3s ease-out;
}
.animated-element:hover {
transform: scale(1.1);
}
Avoid animating layout-triggering properties like width, height, margin, padding, top, or left. These cause browser reflow and shift surrounding content.
Expected vs. Unexpected Layout Shifts
User-Initiated Shifts (Excluded from CLS)
Layout shifts that occur in response to user interactions are generally fine and don't count toward CLS if they happen within 500 milliseconds of the interaction. The browser sets the hadRecentInput flag for these shifts, excluding them from calculations. Examples include clicking a "Show more" button that expands content, tapping a filter that reorders results, typing in a search box with suggestions, or opening accordions and disclosure widgets.
Expected Animations (Excluded from CLS)
Well-designed animations and transitions that guide users through state changes are acceptable. The key is predictability--users should anticipate the movement. Examples include smooth transitions between page states, progressive disclosure of content, and micro-interactions with clear visual feedback. These follow accessibility best practices and respect user preferences through prefers-reduced-motion.
Unexpected Shifts (Counted in CLS)
Any layout change users don't expect or control counts toward CLS. These include content shifting as users read, buttons moving as users try to click, forms rearranging while typing, ads appearing between paragraphs, and chat widgets popping up during reading. The distinction between expected and unexpected shifts is crucial for user experience design.
Images
All images have width and height attributes to reserve space
Ads & Embeds
Fixed or min-height dimensions for all dynamic content
Fonts
Critical fonts preloaded with font-display: swap enabled
Dynamic Content
Skeleton loading states and stable positioning
Animations
Only transform and opacity animated, no layout changes
Testing
CLS score of 0.1 or less in Lighthouse audits
Frequently Asked Questions
Sources
- web.dev: Cumulative Layout Shift (CLS) - Google's official documentation on CLS metric definition, measurement, and calculation
- web.dev: Optimize Cumulative Layout Shift - Google's official optimization guide with code examples and best practices
- Chrome for Developers: Layout shift culprits - Chrome DevTools insights on identifying CLS issues
- DebugBear: Measure And Optimize Cumulative Layout Shift - Technical measurement guide