TroubleshootingIntermediate

Fix Cumulative Layout Shift (CLS)

Layout shifts frustrate users and hurt SEO. Identify unstable elements, reserve space for dynamic content, optimize font loading, and maintain visual stability.

13 min read
Atatus Team
Updated March 15, 2025
6 sections
01

Understanding Cumulative Layout Shift

CLS measures visual instability—how much page content moves unexpectedly during loading.

Cumulative Layout Shift (CLS) measures the total amount of unexpected layout movement that occurs during the entire lifespan of a page. Each layout shift is scored by multiplying the impact fraction (the proportion of the viewport affected) by the distance fraction (how far the element moved as a proportion of the viewport height). A score of 0 indicates perfect stability; a score above 0.1 indicates visible shifting that users will notice; a score above 0.25 is considered poor and means significant content is moving visibly during page load.

Layout shifts are scored only when they are unexpected—shifts that occur within 500 milliseconds of a user interaction (click, scroll, key press) are excluded from the CLS calculation. This means that UI expansions triggered by button clicks, dropdown menus opening, and accordion sections expanding do not contribute to CLS even though they move content. Only shifts that happen without any preceding user input are counted. This distinction is important: focus on fixing shifts that happen during page loading, font switching, and ad injection rather than worrying about interactive UI transitions.

The most jarring layout shifts from a user experience perspective are those that cause users to click the wrong element. A user who positions their cursor to click a 'Read More' button and then the button moves down because an ad loaded above it will either click the ad accidentally or miss the button entirely. This class of layout shift—where an element shifts out from under the user's cursor between mouse-down and mouse-up—can cause accidental purchases, accidental form submissions, or missed clicks on important actions. Prioritize fixing shifts that occur in interactive page areas above the fold.

CLS can occur both during initial page load and during the page's lifetime as content is dynamically inserted or modified. Initial load CLS comes from resources that are not given reserved space (images without dimensions, fonts causing FOUT), while post-load CLS comes from dynamically injected content (late-loading ads, cookie consent banners, push notification prompts, chat widgets). Measure CLS over the full page lifetime, not just during initial load, to capture all sources of cumulative layout shift.

02

Track Layout Shifts on All Pages

Monitoring CLS in real user conditions reveals shifts that lab testing may miss.

Use the Web Vitals JavaScript library or a direct PerformanceObserver on the 'layout-shift' entry type to collect CLS measurements from real users. CLS values are typically reported at page unload (via sendBeacon) or after a page becomes hidden, capturing the cumulative score over the full page session. Send CLS data to your analytics platform along with page URL, user agent, and session duration, as CLS can accumulate during long user sessions. Target P75 CLS under 0.1 to achieve a Good Core Web Vitals rating.

Identify which elements are causing layout shifts using the PerformanceObserver layout-shift entry's sources array, which lists the elements that shifted and the rectangles they shifted from and to. Log this data alongside the shift score so you can identify the specific elements causing your worst shifts. A shift with a score of 0.15 coming from an element identified as the cookie banner is immediately actionable—you know exactly which element to fix without manual testing across all scenarios.

Segment CLS data by page template, viewport size, and device type, as layout shifts often affect mobile users more than desktop users. A sidebar ad that inserts above content on mobile (shifting the main content down) may not cause any layout shift on desktop (where the ad loads in a fixed sidebar column). Monitor CLS on mobile viewports (360px to 414px width is representative of most Android and iPhone models) as a separate metric from desktop CLS, since mobile users are often your highest-traffic segment and may experience worse CLS due to responsive layout differences.

Use Chrome DevTools' Performance panel or the Layout Instability debugger to capture and replay layout shifts during development. Record a performance profile during page load, then look for layout shift events in the Experience lane. Clicking on a layout shift event shows the affected elements highlighted in the viewport at the time of the shift. This visual debugging approach identifies shifts that are too brief or subtle to notice while manually testing the page, particularly shifts that happen before any content is visible.

03

Fix Images and Media Without Dimensions

Images without reserved dimensions are the most common cause of CLS.

Images without explicit width and height attributes cause layout shifts because the browser does not know how much space to reserve for them before they load. When the image loads and the browser renders it at its natural dimensions, all content below the image is pushed down to make room—a classic layout shift. Add explicit width and height attributes to all img elements, or use the CSS aspect-ratio property to reserve space proportional to the image's intrinsic dimensions. Modern browsers use the width and height attributes to calculate aspect ratio and reserve space even when CSS scales the image differently than its natural size.

Responsive images that are scaled with CSS (max-width: 100%; height: auto;) used to require explicit dimensions to prevent CLS, but modern browsers calculate aspect ratio from the HTML width and height attributes even when the actual rendered size differs. Setting width='800' height='600' on an image that is displayed at 400px wide tells the browser to reserve a 4:3 aspect ratio space regardless of the rendered pixel dimensions. This native aspect ratio calculation eliminates CLS for responsive images without requiring inline aspect-ratio CSS on each image.

Video elements require explicit width, height, and aspect-ratio CSS just like images, as the browser has no way to know a video's dimensions before the metadata loads. The time between the page rendering the video element and the video metadata loading (which reveals dimensions) is a window during which the browser reserves zero height for the element. Videos embedded via the HTML video element or via iframes for YouTube/Vimeo embeds both require reserved space. Use the CSS padding-top trick (padding-top: 56.25% for 16:9 aspect ratio) or the CSS aspect-ratio: 16/9 property on a container element to reserve correct space before the video metadata loads.

Dynamic image carousels and sliders that change the displayed image during page interaction can cause layout shifts if the images have different aspect ratios and no fixed container dimensions. Fix this by setting a fixed height on the carousel container, or by ensuring all carousel images share the same aspect ratio through server-side image cropping and resizing. An image carousel that cycles between a 4:3 image and a 16:9 image without a fixed-height container will shift the page content below the carousel with every slide transition.

04

Prevent Font Loading Layout Shifts

Web font loading causes Flash of Unstyled Text (FOUT) that can create layout shifts.

Font loading causes layout shifts when the browser renders text with a fallback system font, then switches to the web font when it loads, and the two fonts have different metrics (different line height, character width, or ascender/descender values) that cause text reflow. The shift happens because different text metrics mean the text block occupies different amounts of space with the fallback font versus the web font. Use font-display: optional to prevent this shift entirely by only using the web font if it is available immediately from cache, falling back permanently to the system font for users who do not have the font cached.

font-display: swap shows the fallback font immediately and swaps to the web font when it loads, causing a FOUT (Flash of Unstyled Text) that generates a layout shift if text metrics differ. font-display: optional uses the web font only if it loads within a very short initial period (approximately 100ms), otherwise uses the fallback font permanently for that page load. For users on fast connections or returning visitors with the font cached, they see the web font with no shift. For users on slow connections, they see the fallback font with no shift. This is the recommended approach for minimizing CLS from fonts.

Preloading critical web fonts eliminates the discovery delay that allows fallback text to render before the web font arrives. If the web font loads before any text is rendered, there is no fallback-to-web-font swap and no layout shift. Preloading ensures the web font is fetched with high priority alongside the page, often completing before any text would be rendered with the fallback font. Use link rel=preload as=font crossorigin for each font variant (weight and style) used in above-the-fold text, prioritizing the fonts most likely to cause significant layout shifts.

CSS size-adjust and ascent-override font properties allow you to adjust fallback font metrics to match web font metrics, reducing the layout shift when the swap occurs. By setting font-size-adjust, ascent-override, and descent-override on the fallback font's @font-face declaration, you can make the fallback font occupy the same space as the web font, resulting in zero shift when the swap occurs. Tools like Font Style Matcher and fontain calculate the correct override values for a given web font and fallback font pairing automatically.

05

Manage Dynamically Inserted Content

Late-loading ads, banners, and dynamic content are major sources of CLS.

Ads are the single most common source of large layout shifts because they load late (after page rendering) and have highly variable sizes. Ad networks do not guarantee the size of ads before they load, making it difficult to reserve exact space. Mitigate ad-related CLS by reserving a fixed-size placeholder for each ad slot—even if the ad is sometimes smaller or larger than the reserved space, a placeholder prevents the worst case of zero reserved space. Set minimum dimensions for ad containers that represent the most common ad sizes and prevent the container from collapsing when no ad loads.

Sticky headers and navigation bars that change height or position after initial render cause CLS when page content jumps to accommodate the changed header. A header that starts tall (showing a promotional banner) and then collapses to a shorter sticky nav bar after scrolling causes CLS as content adjusts to the new header height. Ensure sticky headers have a fixed height or that content has appropriate top margin accounting for the maximum possible header height throughout the page lifecycle. Position changes of fixed or sticky elements that do not affect document flow do not contribute to CLS.

Cookie consent banners and GDPR overlays that appear after the page loads are significant sources of CLS because they insert large content blocks at the top of the page, pushing all existing content down. For consent banners that must be shown to new users, overlay them on top of content (using fixed or absolute positioning) rather than inserting them into the document flow. Fixed-position overlays that do not shift surrounding content have zero CLS impact. If the overlay must push down content, show it server-side before rendering any other content so users never see the shift.

Single-page application route transitions can cause CLS when the new page's layout differs from the previous page's layout and content shifts during the transition. Implement page transition animations that maintain visual continuity, or use a brief fade-out/fade-in transition that ensures users do not observe content shifting. Sharing layout components (header, footer, sidebar) between routes prevents these elements from jumping between route transitions, and ensuring consistent content heights between loading states and loaded states eliminates CLS during data fetching.

06

Establish Visual Stability Standards

Organizational practices and development standards sustain CLS improvements over time.

Include CLS in your performance budgets and CI/CD pipeline checks alongside LCP and FID. Run Lighthouse or WebPageTest against your critical pages after every deployment and fail the pipeline if CLS exceeds 0.1. Because many CLS causes are visually obvious when tested in the browser, include manual visual testing of layout stability as part of your QA process: load pages on slow network throttling, observe the entire loading process, and check for any visible content movements. Synthetic CLS measurement and manual visual QA are complementary because automation catches consistent shifts while manual testing can detect intermittent or network-timing-dependent shifts.

Code review guidelines for UI components should include CLS considerations as a checklist item. Every pull request that adds images, embeds, ads, or dynamic content insertions should be reviewed for CLS risk. Check that new images have explicit width and height attributes, that dynamic content insertions reserve space with placeholder elements, and that new web fonts have appropriate font-display settings. The reviewer asking 'where does this element reserve its space before loading?' for every new dynamic element significantly reduces the number of CLS regressions that reach production.

Component libraries and design systems should build CLS prevention in by default. Image components in your design system should always require width and height props (or enforce aspect-ratio via CSS), preventing developers from accidentally omitting them. Ad slot components should always render with a minimum-height placeholder. Font loading utilities should use the appropriate font-display strategy. When CLS best practices are encoded in the components themselves, individual developers cannot accidentally create CLS by using the component incorrectly.

Set up real-time CLS alerting that notifies when CLS scores degrade beyond your defined thresholds in production. A CLS regression from 0.05 to 0.15 after a release indicates a specific change introduced layout instability. The alert should include the page URL, the percentile that exceeded the threshold, and ideally the element sources causing the shift (from the layout-shift PerformanceObserver data). Rapid alerting enables quick investigation while the code change is recent and the fix is straightforward.

Key Takeaways

  • Always add explicit width and height attributes to img elements—modern browsers use these to calculate aspect ratio and reserve space even when CSS scales the image to different dimensions
  • font-display: optional prevents font-swap layout shifts by only using the web font if it loads within a brief initial window, permanently using the fallback font otherwise
  • Ad slots are the largest source of CLS on most commercial sites—reserve fixed-minimum-height containers for all ad slots to prevent zero-height-to-ad-height shifts
  • Cookie consent banners should use fixed or absolute positioning that overlays content rather than inserting into document flow, which shifts all page content down when displayed
  • Include CLS checks in CI/CD pipeline and code review guidelines—asking 'where does this element reserve its space before loading?' during review prevents most CLS regressions before deployment
  • Layout shifts within 500ms of user input are excluded from CLS scoring—only shifts during page loading and without user interaction contribute to the score
Get started today

Monitor your applications with Atatus

Put the concepts from this guide into practice. Set up full-stack observability in minutes with no credit card required.

No credit card required14-day free trialSetup in minutes

Related guides