Back

Preventing Layout Shift with Modern CSS

Preventing Layout Shift with Modern CSS

Unexpected content jumps frustrate users and hurt your Core Web Vitals scores. Cumulative Layout Shift (CLS) measures these jarring movements—not just during initial load, but throughout the entire page session. A button you’re about to click suddenly moves. Text reflows as fonts swap in. An embed pushes content down mid-scroll.

Modern CSS gives you precise tools for preventing layout shift before it happens. This article covers the CSS-first techniques that work in production today, focusing on intrinsic sizing, font stability, and animation patterns that keep your CLS score under the 0.1 threshold.

Key Takeaways

  • CLS accumulates across the full page lifecycle, not just during initial load—real-user monitoring often reveals higher scores than lab tools
  • Declare intrinsic dimensions using aspect-ratio, width, and height attributes to reserve space before content arrives
  • Use size-adjust and metric override properties in @font-face declarations to eliminate font-swap reflow
  • Animate only transform and opacity properties to avoid triggering layout recalculation

Why CLS Extends Beyond Page Load

CLS accumulates across the full page lifecycle. Lab tools like Lighthouse capture load-time shifts, but real-user monitoring (RUM) often reveals higher scores. The difference? Post-load shifts from lazy content, late-injecting ads, or transitions that exceed the 500-millisecond grace period after user interaction.

Shifts occurring within 500ms of a qualifying user input don’t count toward CLS—they’re expected. Everything else does. This means scroll-triggered lazy loading, hover states that resize elements, and client-side route transitions all contribute if they cause unexpected movement.

Reserving Space with Intrinsic Sizing

The foundation of preventing layout shift is declaring dimensions before content arrives. Modern CSS makes this straightforward.

Images and Media

The aspect-ratio property lets browsers reserve space using only a ratio, without fixed pixel values. Combined with width and height attributes on <img> elements, browsers calculate reserved space immediately during HTML parsing.

For responsive images, set dimensions on <source> elements within <picture> to handle art direction without shifts. The browser uses these values to establish aspect ratios before any image data downloads.

Embeds and Dynamic Content

Third-party embeds—videos, maps, social posts—rarely communicate their final dimensions. Use min-height or aspect-ratio on container elements to reserve expected space. When exact dimensions are unknown, reserve space for the most common size based on your analytics, accepting minor shifts for outliers.

For content injected via JavaScript, the same principle applies: containers should have intrinsic size declared in CSS before scripts execute.

Font Loading Without Reflow

Web fonts cause shifts when fallback and final fonts have different metrics. The font-display property alone doesn’t solve this—swap still causes reflow when metrics differ.

Metric-Aligned Fallbacks

Modern CSS offers size-adjust, ascent-override, descent-override, and line-gap-override within @font-face declarations. These properties tune your fallback font’s metrics to match your web font, eliminating visible reflow even when the swap occurs.

Pair this with font-display: optional for the strictest CLS prevention—the web font only renders if it’s available during initial layout. For less aggressive approaches, metric overrides with font-display: swap provide readable text immediately while minimizing shift magnitude.

Preloading critical fonts with <link rel="preload"> increases the chance they’re available for first paint, reducing the window where fallbacks display.

Animations and UI Expansion

Animating width, height, top, left, or margin triggers layout recalculation and contributes to CLS. Animating transform and opacity doesn’t—these properties run on the compositor without affecting document flow.

Safe Animation Patterns

Scale elements using transform: scale() rather than changing dimensions. Move elements with transform: translate() instead of positional properties. These approaches create visual movement without shifting surrounding content.

For expanding UI—accordions, dropdowns, tooltips—the shift is acceptable when it follows user interaction within 500ms. If expansion happens automatically or after a delay, reserve the maximum expanded space upfront or position the expanding element outside document flow using position: absolute or overlay patterns.

Transitions on Route Changes

Single-page applications often trigger CLS during client-side navigation. If transition animations exceed 500ms or content loads asynchronously after navigation, shifts count against your score. Keep transitions brief and ensure incoming content has reserved space via skeleton placeholders or fixed container dimensions.

Validating Your Approach

Chrome DevTools’ Performance panel shows individual layout shifts with their scores and affected elements. The Layout Shifts track visualizes shift clusters, helping identify patterns.

For production monitoring, RUM solutions using the web-vitals library capture real user CLS with element attribution. Compare field data against lab measurements—discrepancies indicate post-load shifts your synthetic tests miss.

Conclusion

Preventing layout shift comes down to one principle: declare intrinsic size for everything before it renders. Use aspect-ratio for media, metric overrides for fonts, and transform for animations. Reserve space for late-loading content, and verify with both lab tools and field data.

Modern CSS for CLS prevention isn’t about tricks—it’s about giving browsers the information they need to allocate space correctly from the start.

FAQs

Google considers a CLS score below 0.1 as good, between 0.1 and 0.25 as needing improvement, and above 0.25 as poor. Aim to keep your score under 0.1 for optimal user experience and Core Web Vitals performance. Monitor both lab and field data since real-user scores often differ from synthetic tests.

Lighthouse measures CLS only during page load in controlled conditions. Real-user monitoring captures shifts throughout the entire session, including lazy-loaded content, late-injecting ads, and user interactions. Post-load shifts that occur after Lighthouse finishes measuring will only appear in field data.

No, font-display swap alone does not prevent layout shift. It ensures text remains visible during font loading but still causes reflow when the web font replaces the fallback. To prevent shift, combine it with metric override properties like size-adjust, ascent-override, and descent-override to match fallback and web font metrics.

No. Animations using transform and opacity properties run on the compositor thread and do not affect document flow, so they do not cause layout shift. Only animations that change layout-affecting properties like width, height, margin, or positional values trigger recalculation and contribute to CLS.

Truly understand users experience

See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..

OpenReplay