MobileCheck

Cumulative Layout Shift: How to Fix CLS on Mobile

Updated October 17, 2026 · Covers: Content jumps while loading

What it means

Cumulative Layout Shift (CLS) measures how much visible content moves unexpectedly while a page is open. You have seen it: you start reading a paragraph, an image above it finishes loading, and the text jumps down. Or you go to tap a link and a banner slides in, so you tap an ad instead.

Each time a visible element changes position between two frames, the browser records a layout shift with a score based on two things: how much of the viewport was affected (impact fraction) and how far the elements moved relative to the viewport (distance fraction). Shifts that happen within 500 milliseconds after a tap, click or key press are excluded, because movement you caused yourself, like opening an accordion, is expected.

Shifts are grouped into session windows: a burst of shifts with less than 1 second between them, lasting at most 5 seconds. A page's CLS is the score of its worst session window. That way a long-lived page isn't punished just for being open a long time, but one bad burst still counts.

Why it matters

CLS is one of Google's Core Web Vitals, with these thresholds:

CLSRating
0.1 or lessGood
0.1–0.25Needs improvement
Over 0.25Poor

Beyond the score, layout shift is a usability problem that is worse on phones. A small screen means one inserted element can push the whole visible area away, and touch users tap where they saw the target a moment ago. Accidental taps on the wrong button or ad are frustrating and can lead to real mistakes, such as adding the wrong item to a cart.

How MobileCheck measures it

MobileCheck records layout shifts with the browser's Layout Instability API while your page loads on each device. Shifts right after input are ignored, as in the official metric. If the total goes above 0.1, the report shows Content jumps while loading; above 0.25 it is marked "poor".

A few honest caveats. This is a lab measurement from a single load, with no real user scrolling or tapping, so it mainly catches shifts during loading. Field CLS can be higher if shifts happen later, for example when ads load as people scroll. Our value adds up all shifts seen during the load rather than picking one session window, so it can be a little stricter than the official number. And the Layout Instability API is implemented in Chromium, so the Android devices in your report give the meaningful CLS values.

Common causes

How to fix it

Give images width and height

Add width and height attributes to every <img> and <video>. Modern browsers use them to calculate the aspect ratio before the file arrives, even when CSS makes the image responsive.

<img src="/img/product.webp" width="800" height="600" alt="Blue running shoe">

img { max-width: 100%; height: auto; }

For containers whose content arrives later, such as a video embed, reserve the box with aspect-ratio:

.video-embed {
  aspect-ratio: 16 / 9;
  width: 100%;
}

Reserve space for ads and embeds

Give ad slots a minimum height that matches the most common ad size for that position on mobile. If no ad fills it, a little empty space is better than a jump.

.ad-slot-top {
  min-height: 250px;
}

Avoid placing ad slots near the top of the content on mobile where possible, since a shift there moves the most content.

Don't push content down with banners

Insert notices in space that is already reserved, or show them as overlays that don't move the page: a fixed bar at the bottom of the screen, for example. Keep overlays small, though. Large fixed bars create a different problem, covered in sticky headers and popups. If new content must appear in the flow, show it in response to a tap so it falls within the input exclusion.

Match fallback fonts to web fonts

Use size-adjust and the ascent/descent overrides on a local fallback font so it takes up about the same space as your web font. Then the swap barely moves anything.

@font-face {
  font-family: "Brand Fallback";
  src: local("Arial");
  size-adjust: 104%;
  ascent-override: 92%;
  descent-override: 24%;
}
body { font-family: "Brand", "Brand Fallback", sans-serif; }

The right percentages depend on your font; tools and framework font loaders can calculate them. Preloading the main font file also shortens the window in which a swap can happen. For other font issues, see web fonts that fail to load.

Animate with transform

Moving an element with transform doesn't change the layout of other elements and isn't counted as a layout shift. Use it instead of animating top, left, margin or height.

/* Shifts layout */
.toast { transition: top 0.3s; }

/* Doesn't shift layout */
.toast { transition: transform 0.3s; }
.toast.is-hidden { transform: translateY(-100%); }

Be careful with late-loading content

Skeleton placeholders work well when they have the same size as the final content. A skeleton that is 100 pixels tall replaced by a 300-pixel card still causes a shift.

How to check the fix

  1. Run the free mobile check again and compare CLS on the Android devices. The screenshots help confirm that banners and ad slots now sit where you expect.
  2. In Chrome DevTools, the Performance panel marks layout shifts on the timeline and highlights the elements that moved. Enable network throttling, because many shifts only appear on slower connections.
  3. Check PageSpeed Insights for field data from real Chrome users, which includes shifts that happen after load as people scroll. It updates over a rolling 28-day window.

To see the jumps yourself, open your site in the phone window and scroll through it as a visitor would.

Frequently asked questions

What is a good CLS score?

Google rates CLS of 0.1 or less as good, 0.1 to 0.25 as needing improvement, and above 0.25 as poor, measured at the 75th percentile of real visits.

Do layout shifts after a tap count against CLS?

No. Shifts within 500 milliseconds after a tap, click or key press are excluded, because the user expects the page to respond. Scrolling does not count as such input.

Why is CLS shown as a dash for iPhone devices?

The Layout Instability API behind CLS is implemented in Chromium, not in Safari's engine, so the report shows CLS for Android devices only. Shifts still happen in Safari; they just cannot be measured there.

Related guides