Cumulative Layout Shift measures unexpected visual movement — elements jumping around after the page has loaded. A score under 0.1 is Good; above 0.25 is Poor. It is one of the more frustrating Core Web Vitals to fix because the causes are spread across images, fonts, ads, and third-party scripts, and the fixes are sometimes in the HTML, sometimes in the CSS, and sometimes in your hosting configuration. A methodical audit is the only way to track them all down.

How CLS Is Calculated

The browser tracks every layout shift — any visible element that moves more than a few pixels after it initially paints. Each shift is scored by multiplying the impact fraction (how much of the viewport the shifted element occupied) by the distance fraction (how far it moved as a percentage of the viewport height). Shifts that occur within 500ms of a user interaction are excluded from the score. The final CLS value is the sum of the largest burst of layout shifts within a 1-second window — called a session window.

The practical implication: one large shift early in the page load can push you into a Poor score even if everything else is stable. Identifying the biggest individual shift and eliminating it first is almost always the most efficient approach.

Images Without Dimensions

This is the most common cause I see in audits. When the browser renders the HTML and encounters an <img> tag without explicit width and height attributes, it allocates zero space for the image. When the image file finally downloads, the browser expands the element and shoves everything below it down the page. Every element that moves registers a layout shift contribution. The fix is always the same: add width and height attributes matching the image’s intrinsic dimensions. The browser uses those values to compute an aspect ratio and reserve the correct space before the image loads, eliminating the shift entirely.

In WordPress, make sure your theme is outputting image dimensions. Themes built before 2019 often strip them. Check with DevTools — if your images lack width and height in the rendered HTML, a theme or plugin is removing them. This is a fast fix with immediate CLS impact.

Dynamically Injected Content

Ads, cookie consent banners, chat widgets, and newsletter popups are all common CLS contributors. They are injected by JavaScript after the main page has painted, and if they push existing content down, every element below them registers a layout shift. The remediation approach depends on the element type:

  • Ad slots: Reserve space with a CSS min-height on the ad container matching the expected ad unit height. An empty 250px container is invisible to users before the ad loads but prevents the shift when the ad arrives.
  • Cookie banners: If it appears at the top of the page, it shifts everything below. Move it to the bottom of the viewport, or reserve space in the layout before the script fires by including a placeholder with the banner’s dimensions.
  • Chat widgets: Most load bottom-right and do not cause CLS if using position: fixed. If yours is shifting content, inspect the CSS — it may be using position: relative or injecting a container that displaces nearby elements.

Web Font Swap

When a custom font loads and replaces the fallback, the text often reflows — different letter spacing, line height, or character width causes visible content movement. This is the FOUT (Flash of Unstyled Text) problem, but it causes CLS when the reflow is large enough to register as a layout shift. Two approaches reduce this: preload the font so it arrives before the first paint (eliminating the swap), or use the CSS size-adjust, ascent-override, and descent-override descriptors on the fallback font to match its metrics to the web font, reducing the reflow delta when the swap happens. The second approach is particularly useful when preloading is not practical — for example, with variable fonts where the exact file URL is hard to predict.

Animations and Transforms

CSS animations that modify top, left, margin, or height cause layout shifts because they change document flow and force the browser to recalculate layout for surrounding elements. Animations that use transform: translate() or opacity do not — they run on the compositor thread and do not affect document flow. If you have hero animations, scroll effects, or entrance animations on content cards, audit whether they are using layout-affecting properties. Switching to transform-based animations is usually a one-line CSS change and eliminates the CLS contribution completely.

Embeds and iframes

YouTube embeds, social media embeds, and other iframes that do not declare their dimensions cause the same problem as undimensioned images. The browser allocates no space, then shifts content when the embed loads. The modern fix is a CSS aspect-ratio wrapper: set aspect-ratio: 16/9 on the container div and width: 100%; height: 100% on the iframe. The browser reserves the correct space before the iframe loads. For YouTube specifically, the lite-youtube-embed library renders a thumbnail placeholder at the correct dimensions and only loads the actual iframe on click — this eliminates the CLS contribution entirely and also improves LCP by removing a heavy third-party script from the initial load.

Diagnosing in DevTools

Open Chrome DevTools, go to the Performance panel, and record a page load. Filter the Experience row for Layout Shift events. Each event shows the element that shifted, the score contribution, and the timestamp. Click the event to see the affected elements highlighted in the viewport. For field data, the Chrome User Experience Report surfaces CLS by URL group in Google Search Console — check the CLS report to see which page templates are failing at scale, then use DevTools to investigate the specific causes on a representative URL.

Validating the Fix

After deploying changes, use PageSpeed Insights to confirm the lab score improved. Then wait for the 28-day CrUX collection window to see field data update in Search Console. Fixes that look perfect in the lab sometimes have limited impact in the field because a third-party script fires inconsistently in the real world — an ad that loads 80% of the time means 80% of page views have the CLS contribution, and your field score reflects that. Field data is the final arbiter.

CLS is one of three Core Web Vitals signals. For the complete remediation workflow — including how to sequence CLS fixes alongside LCP and INP work — see Core Web Vitals optimization. A website audit will surface CLS issues alongside the rest of the technical stack so nothing gets missed in the process.