Avoid CSS Cumulative Layout Shifts for Better User Experience

Learn the causes of layout shifts and practical techniques to prevent them. Improve your Core Web Vitals scores and create stable, predictable web experiences.

Cumulative Layout Shift (CLS) is one of Google's Core Web Vitals metrics that measures how stable and predictable a web page appears during loading. When elements suddenly jump around the page--pushing content you've started reading or buttons you've clicked out of place--visitors experience frustration and disengagement.

This guide covers the causes of layout shifts and practical techniques to prevent them in your CSS and HTML. Implementing these optimizations is essential for technical SEO and delivering professional user experiences.

CLS Thresholds

0.1or less

Good CLS Score

0.25or greater

Poor CLS Score

75% of page visits

Percentage Required

What Is Cumulative Layout Shift (CLS)?

CLS quantifies the visual stability of a webpage by measuring two factors: how much visible content shifted in the viewport, and the distance the affected elements moved. Unlike other Core Web Vitals measured in seconds or milliseconds, CLS produces a unitless score based on these calculations.

Why CLS Matters for Your Website

Layout shifts create disorienting experiences that interrupt user attention and task completion. When a user attempts to click a button or read text, sudden movement can cause accidental clicks or lost reading position. Beyond the immediate usability issues, poor CLS scores directly impact search engine rankings since Google uses Core Web Vitals as ranking signals.

Understanding the CLS Score

The CLS score combines the impact fraction (percentage of viewport affected) with the distance fraction (how far elements moved). Good CLS scores fall at 0.1 or below, while scores above 0.25 indicate poor performance requiring immediate attention.

Common Causes of Layout Shifts

Several common patterns create layout shifts in web pages. Understanding these patterns helps you apply targeted solutions.

Images Without Dimensions

Images without width/height attributes cause shifts when the browser calculates their size after loading.

Ads and Embeds

Third-party content like ads, videos, and iframes often load without reserved space.

Dynamic Content

Content injected after initial load--banners, notifications--pushes existing content downward.

Web Fonts

Font swapping can change text dimensions, causing paragraphs to reflow and shift.

Images Without Dimensions

Images represent one of the most frequent causes of layout shifts because browsers cannot determine their dimensions until the image file loads. Without explicit width and height attributes, the browser reserves zero space for images until they arrive, then adjusts the layout to accommodate the actual image size.

<!-- Problem: No dimensions specified -->
<img src="hero-image.jpg" alt="Hero image">

<!-- Solution: Width and height attributes -->
<img src="hero-image.jpg" width="800" height="600" alt="Hero image">

Modern browsers use the width and height attributes to calculate an aspect ratio that reserves appropriate space before the image loads. Combined with CSS that sets width: 100% and height: auto, this approach maintains responsive behavior while preventing layout shifts. For responsive images using srcset, ensure all source options share the same aspect ratio.

See our guide on using CSS filters and SVGs to learn more about responsive image techniques.

Ads, Embeds, and Iframes Without Dimensions

Advertising networks, embedded videos, and third-party iframes frequently cause layout shifts because their dimensions are unknown until runtime. The solution involves reserving space for dynamic content using CSS with fixed aspect ratios or explicit dimensions.

/* Reserve 16:9 space for video containers */
.video-container {
 aspect-ratio: 16 / 9;
 width: 100%;
}

/* Advertisement slot with reserved minimum space */
.ad-slot {
 min-height: 250px;
 background-color: #f8f9fa;
}

For advertisement slots, define a minimum height based on expected ad sizes. For iframes, always specify width and height attributes, or use CSS aspect-ratio to reserve space proportionally. Some publishers wrap ad slots in containers with set dimensions and display placeholder content until the actual ad loads.

Learn more about building responsive layouts with the CSS :has() selector that accommodate dynamic content gracefully.

Web Fonts and Font Loading

Web fonts can cause layout shifts in two ways: Flash of Invisible Text (FOIT) and Flash of Unstyled Text (FOUT). When a font file is downloading, browsers either display fallback text until the custom font arrives or hide text entirely.

The font-display CSS descriptor controls how browsers handle font loading:

<!-- Preload critical font -->
<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; /* Text visible immediately */
}
</style>

Using font-display: swap displays fallback text immediately while the custom font loads, then swaps to the custom font once available. The font-display: optional value only uses the custom font if it's already cached, preventing the swap entirely.

Explore our guide on styling links with CSS for more typography optimization techniques.

Prevention Strategies Quick Reference

Add Dimensions

Always include width and height attributes on img and video elements.

Use aspect-ratio

CSS aspect-ratio reserves space for responsive elements.

Set min-height

Establish minimum dimensions for dynamic content containers.

Optimize Fonts

Use font-display strategies and preload critical fonts.

CSS Containment

Use contain: layout to isolate component reflows.

Fixed Positioning

Position overlays outside document flow to prevent shifts.

Testing and Measuring CLS

Using Chrome DevTools Performance Panel

  1. Open Chrome DevTools (F12)
  2. Navigate to the Performance panel
  3. Record a page reload
  4. Look for the "Layout Shifts" track with purple bars
  5. Click on shifts to see animated playback and affected elements

For automated testing approaches, explore our guide on using Puppeteer for automated UI testing.

Lighthouse and PageSpeed Insights

Lighthouse provides CLS measurements in a controlled lab environment, while PageSpeed Insights shows both lab data and real-user field data from CrUX. When field and lab scores differ, investigate post-load shifts that occur after the lab test completes.

Monitoring CLS in Production

Use the Layout Instability API via Performance Observer to capture CLS data from actual visitor sessions:

const observer = new PerformanceObserver((list) => {
 for (const entry of list.getEntries()) {
 console.log('Layout shift:', entry.value);
 }
});
observer.observe({ type: 'layout-shift', buffered: true });

Combine this with our web development services to implement continuous performance monitoring across your digital properties.

Animations and Transitions Best Practices

Use CSS transforms for all animations since transforms don't trigger layout recalculation. Avoid animating properties like height, width, margin, padding, top, or left--any property that affects layout geometry. For an in-depth look at animation properties, see our guide on CSS animation-direction.

/* Good: Transform animation doesn't trigger layout */
.animate-fade {
 transition: opacity 0.3s ease;
 will-change: opacity;
}

/* Avoid: Height animation triggers layout recalculation */
.animate-expand {
 transition: height 0.3s ease; /* Triggers layout */
}

For modal dialogs and overlays, use transforms for entrance animations and fixed positioning to prevent document reflow. These approaches maintain smooth animations while preserving layout stability.

Discover more techniques for creating custom dropdown selects with CSS that balance visual appeal with performance.

Frequently Asked Questions

What is a good CLS score?

A good CLS score is 0.1 or less for at least 75% of page visits. Scores above 0.25 are considered poor and should be addressed immediately.

Do layout shifts from user interactions count?

No. Layout shifts that occur within 500 milliseconds of a user interaction (like a click or tap) are excluded from the CLS calculation because they are expected responses to user input.

Can I prevent layout shifts from third-party ads?

Yes. Reserve space for ad slots using CSS min-height or aspect-ratio. Even if ads fail to load or load smaller creatives, the reserved space prevents surrounding content from shifting.

What if I can't know content dimensions in advance?

Use reasonable minimum dimensions based on expected content sizes. For user-generated content, establish maximum character counts or use truncation with consistent height containers.

How do I test CLS on mobile devices?

Use Chrome DevTools Device Mode to simulate mobile viewports, or test on actual devices using remote debugging. Field data from Chrome UX Report shows real mobile user experiences.

Conclusion

Cumulative Layout Shift directly impacts how users perceive your website's quality and professionalism. By reserving space for all content before it loads, specifying dimensions for media elements, optimizing font loading strategies, and testing layouts across conditions, you can achieve CLS scores that delight users and satisfy search engines.

The techniques covered in this guide address both common layout shift patterns and sophisticated scenarios, providing a comprehensive toolkit for creating stable, predictable web experiences. Implementing these practices as part of your web development workflow ensures consistent performance across all your digital properties.


Sources:

  1. Google web.dev: Optimize Cumulative Layout Shift
  2. BrowserStack: Understanding Cumulative Layout Shift
  3. Natclark: How to Fix CLS in 2025

Ready to Optimize Your Website's Performance?

Our team specializes in building fast, stable web experiences that users love. Let us help you achieve excellent Core Web Vitals scores.