QuestionsWeb Performance

Eliminating layout shift at the source

Layout Stability (CLS)HardWeb Performance

CLS is 0.35 and content jumps as the page loads. Enumerate the root causes and the fix for each.

What it tests

A systematic account of what shifts layout and how to reserve space or avoid the shift entirely.

Approach & answer

CLS accumulates every time visible content moves without a user action; each shift is scored by how much of the viewport moved and how far. The causes are a short, fixable list. (1) Media without dimensions — images, videos, iframes, embeds that have no reserved box collapse to zero then push content down when they load. Fix: set width/height attributes or CSS aspect-ratio so the box is reserved before bytes arrive. (2) Web fonts — the swap from fallback to web font changes text metrics and reflows. Fix: font-display: optional, or match fallback metrics with size-adjust/ascent-override, and preload the font. (3) Dynamically injected content above existing content — banners, cookie notices, ad slots, 'you have new messages' bars inserted at the top shove everything down. Fix: reserve space for known slots (min-height on the ad container), or inject below the fold / overlay instead of in-flow. (4) Actions that resize without space reserved — an accordion or 'read more' that expands is user-initiated (within 500ms of input it's excluded from CLS), but async expansions are not. (5) Animating layout properties — animating top/left/height moves surrounding content; animate transform/opacity instead (composited, no reflow, no shift). (6) Late-arriving data that changes sizes — skeletons should match the final content's dimensions so the real content drops in without resizing. The unifying principle: reserve the final space up front and never insert or grow in-flow content above what the user is looking at. Measure which element shifted using the LayoutShift entries' `sources` in DevTools to target the actual culprit rather than guessing.

Use this technique when

Driving CLS below 0.1; auditing a page that visibly jumps during load.

Code

<!-- Reserve the media box so nothing jumps when it loads -->
<img src="hero.webp" width="800" height="450" alt="…">
<div style="aspect-ratio: 16/9;"><iframe src="…"></iframe></div>

<!-- Reserve space for an async ad/slot instead of letting it push content -->
<div class="ad-slot" style="min-height:250px"></div>

<style>
  /* Animate composited props: moves the element, not its neighbors */
  .toast { transition: transform .2s, opacity .2s; }
  /* NOT: top / height / margin, which reflow surrounding content */
</style>

References