CLS element movement

This health check detects individual elements that cause cumulative layout shift (CLS) based on real user data.

Instead of just showing that CLS is high, this check pinpoints the specific elements moving on the page, so you can fix the root cause.

Each todo represents a single element that shifts significantly for a specific device type.

About this check

When this check is triggered

You’ll see this check when:

  • An element contributes significantly to CLS
  • The issue is consistent across real users
  • There are enough events (minimum threshold applied)
  • The impact is visible in higher percentiles (p75, p85, p90)

What you’ll see

Each todo includes:

  • Element identifier
  • Device type (desktop, mobile, tablet)
  • Impact based on real user sessions

Example:

Element moved significantly on mobile
The element .hero-banner img is moved around heavily on mobile.

Why this matters

CLS directly impacts:

  • User experience (unexpected jumps)
  • Conversion rates
  • Core Web Vitals performance

Even small shifts can feel disruptive, especially on mobile.

More context on web.dev and RUMvision CLS blogpost.

How to fix it

Most CLS issues come from:

  • Images or videos without dimensions
  • Ads, embeds, or iframes loading late
  • Fonts causing layout changes (FOIT/FOUT)
  • JavaScript injecting content above the fold
  • Dynamic UI components (banners, cookie notices)

Possible causes and fixes:

1. Reserve layout space

Ensure elements have a defined size before they load.

What to do

Example

img alt="Hero" height="400" src="hero.jpg" width="800"
.video {
aspect-ratio: 16 / 9;
}

2. Stabilize UI updates

Avoid pushing content down after initial render.

What to do

  • Do not inject banners above existing content
  • Use placeholders or skeleton loaders
  • Render critical UI elements immediately

For example, instead of:

setTimeout(() => {
showCookieBanner();
}, 2000);

Use:

  • Reserved space
  • Or overlay instead of pushing layout

3. Handle fonts properly

Web fonts can cause subtle but frequent layout shifts.

What to do

  • Preload critical fonts
  • Use font-display: swap
  • Match fallback font metrics to the web font where possible
  • For example with more modern solutions like CSS Font descriptors

Elements that become sticky on scroll often do not reserve space for the underlying content. This causes the content below to shift when the element becomes sticky.

What to check

  • Toggling an element from position:relative to position:fixed on scroll
  • Use modern and browser compatible alternatives like position:sticky within scrollable containers
  • Alternatively, apply position:absolute or fixed from the start and use a placeholder with matching height.

5. Use hardware accelerated animations

Animations on the main thread can easily trigger layout shifts.

What to check

  • Avoid animating all properties (e.g. transition: all 0.2s ease)
  • Limit animations to transform properties (e.g. transition: transform 0.2s ease)
  • To then use transform:translateY(-100px) instead of top:-100px to animate positional changes of elements

6. Audit third-party scripts

Third-party scripts are a common source of layout shifts.

What to check

  • Ads resizing after load
  • Ad rotating system that is clearing contents in between ad-rendering
  • A/B testing tools injecting DOM changes
  • Chat widgets appearing above content
  • Cookie or newsletter widgets that are sliding into screen with wrong CSS properties (see 5. Use hardware accelerated animations)

7. Dynamic content

Avoid layout shifts from dynamic content by both 3rd and 1st party scripts.

What to check

  • Content inserted via API after initial render
  • Hydration mismatches where server HTML differs from client render
  • Late-loading recommendations or related content
  • Infinite scroll appending above fold content
  • YouTube, maps, social embeds resizing after load

8. Scrollbar jitter

Avoid shifts caused by scrollbar appearance

What to check

  • Layout width changes when scrollbar appears/disappears

Remediation:

html {
overflow-y: scroll;
}

or a Newly Available solution:

scrollbar-gutter: stable;

Further debugging

How to approach this in RUMvision

  1. Open the todo
  2. Inspect the element selector
  3. Reproduce the issue:
  4. Identify what triggers the movement
  5. Apply one of the fixes above
  6. Monitor improvement in the next 7 days

Pro tip

Focus on:

  • both above and below-the-fold elements, while you may want to start with above-the-fold shifts
  • Mobile first (usually worse CLS)
  • Recurring components (headers, hero blocks, ads)

Fixing one component can resolve multiple CLS issues at once.