/ โ† CLS Debugger Fixes / CLS from Dynamic Content
In this guide
  1. Why late content counts as a shift
  2. Finding late insertions
  3. The fix, step by step
  4. Overlay, reserve, render early or wait: choosing for each element
  5. Cookie and consent notices in detail
  6. Experiments and personalisation
  7. Stopping new insertions creeping back
  8. Questions and answers

Why late content counts as a shift

Adding something new to a page is not itself a layout shift. What counts is existing, visible content changing position as a result. So a notice that appears in empty space, or on top of the page, costs nothing. The same notice inserted at the top of the document costs a great deal, because every line of text on the screen moves down by its height.

There is an important exception. Shifts within half a second of a click, tap or key press are ignored, because the visitor caused the change and expects it. That means the problem is specifically content that arrives on its own:

The last one surprises people. The visitor did click, but the insertion happened more than 500 milliseconds later, so the grace period had ended by the time the page moved.

๐Ÿ’ก Removing content causes shifts too. A block that is shown by default and then hidden by a script, such as a "read more" section that collapses after load or a notice that is removed once a script sees it was already dismissed, pulls everything below it upwards.

Finding late insertions

Late content is often only shown to new visitors, or only in some regions, so the page may look stable to you because you dismissed everything months ago.

  1. Open a private window so there are no cookies or stored settings. Run the CLS Debugger and note the shifts and the elements named.
  2. In Chrome DevTools, record a reload in the Performance panel with slow throttling. Wait at least 15 seconds without touching the page, since timed prompts often appear after a delay, then scroll slowly to the bottom.
  3. Select each shift and look at what appeared, disappeared or changed size directly above the elements that moved.
  4. Repeat after accepting cookies, and after refusing them. Consent choices change what loads.

To catch insertions as they happen, you can log every element added to the page after load, alongside the shifts:

new MutationObserver((records) => {
  for (const r of records) {
    r.addedNodes.forEach((n) => {
      if (n.nodeType === 1) console.log('added', Math.round(performance.now()), n);
    });
  }
}).observe(document.body, { childList: true, subtree: true });

Match the timestamps against the shift times in the Performance panel. An element added a moment before a large shift, above the content that moved, is your culprit.

โš ๏ธ Some tools only show their content to visitors from certain countries, or on a visitor's second page. If your debugger run is clean but real-user CLS is poor, try a VPN location that matches your audience and click through two or three pages.

The fix, step by step

Step 1

List what appears after the first paint

In a private window with slow throttling, record a reload, wait at least 15 seconds without touching anything, then scroll to the bottom. Note every notice, prompt, message or block that appears, disappears or changes after the page first draws, and whether it sits in the normal flow of the page. Compare the list with the elements the CLS Debugger reports, and rank them by the size of the shift each one causes.

Step 2

Turn consent notices into overlays

In your consent tool's appearance settings, choose a layout that floats over the page, such as a bottom sheet, a corner box or a centred dialog, rather than a bar that pushes content down. If the notice is custom-built, give it position: fixed so it sits above the content instead of inside it. Make sure the preferences panel it opens is also an overlay, and that the notice does not cover the whole screen on phones.

Step 3

Show prompts and age checks on top of the page

Newsletter sign-ups, discount offers, surveys and age checks should appear as fixed-position dialogs or slide-ins, never as blocks inserted into the article. If a prompt must sit inside the content, such as a sign-up box halfway down a post, output its container in the HTML with its final height so the form fills a space that already exists. Animate any entrance with transform and opacity, not height or margins.

Step 4

Decide personalised content before the page is sent

Messages based on location, login state, basket contents or an experiment variant should be chosen on the server or at the CDN edge and included in the HTML, so the first paint is already correct. If that is not possible, reserve the block's space with a fixed min-height and fill it later. Avoid testing tools that swap content in the browser after load, and anti-flicker snippets that hide the whole page while they run.

Step 5

Insert new items only below or on request

For feeds, comments and live updates, never add new entries above what the visitor is reading. Show a small fixed button such as "3 new posts" and insert them when it is tapped. For "load more" buttons, add placeholder rows immediately on click, within the half-second grace period, and fill them when the data arrives. With infinite scroll, append below the viewport and keep the footer out of the loaded area.

Step 6

Give deferred sections an intrinsic size

If you use content-visibility: auto to skip rendering off-screen sections, always pair it with contain-intrinsic-size, for example contain-intrinsic-size: auto 600px, so each skipped section keeps a realistic height. Without it the sections collapse to zero and grow as the visitor scrolls towards them. The auto keyword lets the browser remember the real height once a section has been rendered for the first time.

Step 7

Retest as a first-time visitor

Clear page and CDN caches, open a new private window and run the CLS Debugger again. Repeat the long, untouched recording and the full scroll, then accept cookies and repeat, then refuse and repeat. Check a phone width, where overlays can cover important content. Over the following weeks, watch real-user CLS, since returning and new visitors see different content and both are included.

Overlay, reserve, render early or wait: choosing for each element

Every late element can be made stable in one of four ways. The right one depends on what the content is for.

ApproachBest forHowWatch out for
OverlayCookie notices, sign-up prompts, age checks, surveys, chat invitationsposition: fixed or a native <dialog>, entering with a transformCovering buttons or text on small screens; trapping keyboard focus without a way out
ReserveA sign-up box within an article, a recommendations strip, a block filled from an APIOutput the container in the HTML with a fixed height or min-heightContent that sometimes does not arrive, leaving a gap; choose a sensible fallback
Render earlyPersonalised greetings, regional messages, experiment variants, logged-in statesDecide on the server or CDN edge and include in the HTMLPage caching: vary the cache by the deciding factor, or cache a neutral version
Wait for the visitorNew items in feeds, more results, expanded detailsInsert on click or tap, with instant placeholders if data is slowResponses slower than half a second still count unless space is added immediately

A native <dialog> opened with showModal() is drawn in the browser's top layer, above everything else, so it never pushes content. It also handles focus and the Escape key for you, which makes prompts more accessible.

.signup-slidein {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  max-width: 22rem;
  transform: translateY(120%);
  transition: transform 0.3s ease;
}
.signup-slidein.is-open { transform: translateY(0); }

Experiments and personalisation

Tools that change content in the browser after load, whether for A/B tests, geotargeted offers or "welcome back" messages, cause two linked problems. If they change the page after it has been drawn, you get layout shifts as headlines rewrap and blocks appear. To avoid visible flicker, many of them offer a snippet that hides the whole page until the test has run, which swaps a CLS problem for a slow first paint and worse LCP.

Better options, in order of preference:

  1. Server-side or edge testing. Assign the variant before the HTML is generated, so each visitor receives a finished page.
  2. Same-size variants. If you must test in the browser, keep variants the same shape: similar headline lengths, images of the same ratio, buttons of the same height.
  3. Test below the fold. Changes to content that is not yet visible do not shift anything the visitor can see.

For page caching, remember that content decided on the server must not be cached and served to the wrong visitor. Either vary the cache by the relevant cookie or region, or serve a neutral version from the cache and reserve space for the personalised block.

Stopping new insertions creeping back

Widgets rendered by JavaScript into a fixed place on the page, such as reviews or product recommendations, are covered by fixing CLS from late-loaded components, and basket and alert bars by fixing CLS from cart and notification banners.

Questions and answers

1. Does a cookie consent banner hurt my CLS score?

Only if it moves other content. A notice inserted into the page, typically as a bar at the top, pushes everything down and can fail the 0.1 threshold on its own because every new visitor sees it. A notice displayed with fixed positioning floats over the page and does not move anything, so it adds nothing to CLS. Most consent tools offer a floating layout in their settings; choose one and check that any preferences panel it opens floats too.

2. Do pop-ups count as layout shift?

A true pop-up, one that appears on top of the page in a fixed-position box or a modal dialog, does not move the content beneath it and so is not a layout shift. Prompts that are inserted into the page itself, such as a sign-up form that appears in the middle of an article after a delay, do push content down and count. The visual design can look similar, so check the element's position in DevTools rather than trusting how it looks.

3. Why does clicking load more still cause layout shift?

Shifts are only excluded if they happen within 500 milliseconds of the click. If your button fetches results from the server and the response takes longer than that, the new items arrive after the grace period and their insertion counts. Add placeholder rows straight away when the button is pressed, so the space changes inside the grace period, then fill them when the data arrives. Also make sure new items are added below the button, not above it.

4. Can A/B testing tools cause CLS?

Yes. Tools that run in the browser change headlines, images or blocks after the original version has been drawn, which moves content if the variants are different sizes. Their anti-flicker snippets avoid visible changes by hiding the page until the test is ready, which hurts loading speed instead. Assigning variants on the server or at the CDN edge avoids both problems. If you must test in the browser, keep each variant the same size as the original.

5. Does removing content from the page cause layout shift?

Yes. When a visible element disappears, everything below it moves up, and that counts in the same way as moving down. Common examples are notices removed by a script once it finds the visitor has already dismissed them, loading messages that vanish, and long text collapsed into a read more link after the page has loaded. Decide what to show before the first paint, using a cookie read on the server, or collapse content in CSS from the start.

6. Does content-visibility auto cause layout shift?

It can if it is used without contain-intrinsic-size. The content-visibility property lets the browser skip rendering sections that are off-screen, but a skipped section has no height by default. As the visitor scrolls towards it, the browser renders it, it grows to its real height and content moves. Setting contain-intrinsic-size to auto with a realistic estimated height gives each skipped section a placeholder size, and the auto keyword remembers the real height after it has been rendered once.

7. Is it better to show a sign-up prompt as a modal or inline?

For layout stability, a modal dialog or a fixed slide-in is safest, because it never moves the content underneath. An inline sign-up box is also fine if its space is already in the HTML when the page loads, so the form fills a gap rather than creating one. What causes shifts is an inline prompt added later by a script. Whichever you choose, make it easy to dismiss and avoid covering the main content on small screens.

Catch content that moves your page

The CLS Debugger records every layout shift while your page loads, names the elements involved, calculates the cumulative score and ranks each shift by its impact, so you can see which late notice or block is pushing content aside.

Open CLS Debugger Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All CLS Debugger Fixes  ·  CLS from Cart and Notification Banners  ·  CLS from Late-Loaded Components  ·  Cookie Consent Fixes  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.