CLS Debugger Fixes: Track Down What Moves and Stop It
Cumulative Layout Shift is the score for content jumping around while someone is trying to read or tap it. The hard part is rarely the fix; it is working out which element moved and what pushed it.
Our CLS Debugger records every layout shift while the page loads, names the elements involved, adds up the score and ranks the shifts by how much each one contributed. This page explains how shifts are counted, how to trace one back to its cause, and which guide fixes each kind of shift.
How a layout shift is counted
The browser reports a layout shift whenever an element that was already visible changes its start position between two frames. New content appearing is not a shift in itself; the shift is the existing content being pushed out of the way.
Each shift gets a score made of two parts multiplied together:
- Impact fraction. How much of the viewport was affected, counting the area the moving elements covered before and after the move.
- Distance fraction. How far the elements moved, as a proportion of the viewport's larger dimension.
So a small badge moving a long way and a large block of text moving a little can score about the same. A full-width banner that pushes the whole article down by a quarter of the screen scores highly on both.
Session windows
Shifts are grouped into bursts called session windows. A window keeps growing while shifts happen less than a second apart, up to a maximum of five seconds. The page's CLS is the total of the worst single window, not the sum of everything that happened during the visit. That is why a long page with occasional small shifts can still pass, while one bad burst during load can fail it on its own.
What does not count
Shifts within 500 milliseconds of a click, tap or key press are excluded, because the visitor expects
the page to change when they act. Moving things with CSS transform animations does not count
either, since transforms do not change layout. Scrolling does not exclude shifts, however: content that
jumps as it lazy-loads during scrolling still counts.
Tracing a shift back to its cause
The debugger gives you the element that moved. That is often not the element that caused the move. If a banner appears at the top of the page and pushes the article down, the report shows the article's paragraphs shifting; the banner is the culprit. Always ask "what appeared or changed size just above this?"
Reproducing it yourself
- Open the page in Chrome with DevTools, go to the Performance panel and record a page reload. Layout shifts appear as their own track; select one to see the nodes that moved and their old and new positions.
- Switch on network and CPU throttling. Many shifts only happen when an image, font or script arrives late, and on a fast connection everything lands before the first paint.
- Repeat with the cache disabled and in a private window, so you see the cookie banner and first-visit behaviour real newcomers get.
- Scroll slowly down the page while recording, because lazy-loaded content and sticky elements often shift further down.
Logging shifts in the console
The Layout Instability API lets you list each shift and its source nodes directly. Paste this into the console before reloading, or add it temporarily to the page:
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.hadRecentInput) continue;
console.log(entry.value.toFixed(4),
entry.sources.map((s) => s.node));
}
}).observe({ type: 'layout-shift', buffered: true });
For real visitors, the attribution build of Google's web-vitals library reports the element responsible for the largest shift, which you can send to your analytics to find shifts that only happen on certain devices or journeys.
Matching what you see to the likely cause
Once you know which element moved and roughly when, the cause is usually one of a small set of patterns. Use this table to go from the symptom to the right guide.
| What you see | Likely cause | Where to look |
|---|---|---|
| Text drops down as a photo appears above it | Image with no width and height, or no reserved aspect ratio | Images guide |
| Paragraphs reflow and headings change width a moment after load | Web font replacing a fallback font with different metrics | Fonts guide |
| A gap opens in the middle of an article and content jumps | Ad slot filled after load with no reserved height | Ads guide |
| Page shifts when a video or social post finishes loading | Embed or iframe without a fixed aspect-ratio container | Video guide |
| Everything moves down when a strip appears at the top | Cookie notice, promo bar or sign-up prompt inserted into the flow | Dynamic content and banner guides |
| Sections pop in below the hero after a pause | Components rendered by JavaScript after the initial HTML | Components guide |
| Image box changes height when the window resizes or rotates | Responsive sources with different proportions | Responsive guide |
The fix guides
Each guide covers one source of shifting: how to confirm it is the cause and how to reserve space or change the loading pattern so nothing moves.
Media and embeds
Fixing CLS from images without dimensions
shows how width and height attributes, or the CSS aspect-ratio
property, let the browser reserve the right box before the file arrives. Fixing
CLS from responsive image swap covers srcset and art-directed sources whose proportions
differ, and how to lock the box whatever file is chosen. Fixing
CLS from video and iframe embeds covers YouTube, Vimeo, maps and social posts, using a fixed-ratio
wrapper.
Text and fonts
Fixing CLS from web font swap covers
font-display choices, preloading key fonts, and adjusting the fallback font with size-adjust
and related descriptors so the swap barely moves anything.
Content added after load
Fixing CLS from ad slots covers reserving a fixed size per slot and handling slots that sometimes stay empty. Fixing CLS from late-loaded components covers skeleton placeholders and minimum heights for widgets rendered by JavaScript. Fixing CLS from dynamic content insertion covers newsletter prompts, cookie notices and age gates, and when to overlay rather than insert. Fixing CLS from cart and notification banners covers "added to basket" bars and alerts that should sit on top of the page, not inside it.
By platform
WordPress covers page builders that output images without dimensions, lazy-loaded blocks and ad plugins. Shopify covers app-injected blocks, announcement bars, theme fonts and product image variants. React and Next.js covers hydration differences, lazy components with placeholders, and the built-in image and font components.
Which shifts to fix first
Because CLS is the score of the worst burst, not the total, you get the biggest improvement by fixing the largest shifts in that burst. The debugger ranks shifts by their contribution, so start at the top of its list.
- Shifts that affect every page. A header, cookie notice, announcement bar or web font is shared across the site, so one fix improves every template at once.
- Shifts above the fold during load. These are what every visitor sees, and they tend to be large because they push the whole page down.
- Shifts near buttons and links. Anything that can make someone tap the wrong thing, such as a "Buy" button moving just as a promo bar appears, costs you sales and trust even if the score is small.
- Shifts further down the page. Lazy-loaded images and ads in long articles matter too, but they usually score lower and affect fewer visitors.
Small shifts under 0.01 each are rarely worth chasing individually unless several of them land in the same session window and add up.
Order of work
- Record the shifts. Run the CLS Debugger on each main template and note the top shifts, the elements named and roughly when they happen.
- Identify the cause, not just the mover. For each big shift, find the element above it that appeared or changed size.
- Reproduce it locally. Use throttling and a fresh private window so you can see the shift happen and confirm your fix removes it.
- Reserve space or overlay. Give media fixed proportions, give ad slots and widgets a minimum height, and move notices into fixed or sticky positions that sit over the content.
- Fix the fonts. Match the fallback font's size to the web font, or use a
font-displayvalue that avoids a late swap. - Re-run the debugger. Confirm the shift has gone and that no new one has appeared lower down.
- Watch real-user data. Field CLS improves over the following weeks as older visits age out of the reporting window.
For more background, see the CLS Guide. If layout shift is one of several speed problems, the page speed fixes cover server response and page weight, and the image optimisation fixes cover image sizing in detail.
1. What is a good CLS score?
A CLS of 0.1 or less is considered good, between 0.1 and 0.25 needs improvement, and above 0.25 is poor. Google judges it at the 75th percentile of real visits, so at least three quarters of page loads need to stay at or under 0.1. The score has no units: it combines how much of the screen moved with how far it moved. A single large banner pushing the page down can use up the whole allowance on its own.
2. Why does my CLS look fine in testing but poor in Search Console?
Lab tests usually record only the initial page load on one device, while Search Console uses real visits over 28 days. Real visitors scroll, rotate phones, see cookie notices, receive different ads and use slower connections, all of which can trigger shifts a lab test never sees. Record a longer session in DevTools with throttling switched on, scroll the whole page, and consider logging shifts from real users with the web-vitals library.
3. Do cookie banners cause layout shift?
They can. A banner that is inserted at the top or bottom of the normal page flow pushes content out of the way, and that movement counts as a layout shift. A banner displayed as an overlay, using fixed positioning so it sits on top of the page, does not move other content and so does not add to CLS. Most consent tools offer an overlay style, and it is usually the better choice for both stability and clarity.
4. Do layout shifts after a click count towards CLS?
Shifts that happen within 500 milliseconds of a click, tap or key press are excluded, because the visitor expects the page to change in response. So opening an accordion or a menu immediately does not count. But if the response takes longer than half a second, for example because content is fetched from the server first, the resulting shift can count. Scrolling is not treated as an input for this purpose, so shifts while scrolling do count.
5. How do I stop web fonts from causing layout shift?
The shift happens when text is first drawn in a fallback font and then redrawn in the web font, which has different letter widths and line heights. You can preload the most important font files so they arrive sooner, choose a font-display value that avoids a late swap, and adjust the fallback font with size-adjust and related descriptors so it takes up almost exactly the same space. Frameworks such as Next.js can generate those adjustments for you.
6. Do I still need width and height on images if I use CSS?
Yes, it is still good practice. Modern browsers use the width and height attributes to work out an image's aspect ratio before it downloads, even when CSS makes the image responsive with a width of 100 per cent and an automatic height. That lets the browser reserve the right amount of space. Without them, the image box starts at zero height and expands when the file arrives. The CSS aspect-ratio property is an alternative when attributes are not practical.
7. Can animations cause layout shift?
Animations that change layout properties, such as top, left, height, width or margin, move surrounding content and can count as layout shifts if they are not triggered by the visitor. Animations that use the CSS transform property, for example translate or scale, do not change layout and are not counted. So for sliding panels, carousels and entrance effects, animate transform and opacity rather than position or size. It is also smoother, since the browser does less work each frame.
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 know exactly where to start.
Run the CLS Debugger โ