# Cumulative Layout Shift sources identified and fixed

- **Pattern:** `ab-002002` (`performance-core.rendering-paint.cls-fixed`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002002
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002002)

## Why it matters

Cumulative Layout Shift (CLS) above 0.1 means content visibly jumps while the user is reading or interacting — a failing Core Web Vitals score (ISO-25010 time-behaviour). The most common causes are images loading without declared dimensions (the browser reserves no space until the image arrives), late-injected ads that push content down, and font swaps that change line heights. A CLS above 0.25 causes accidental taps on the wrong element and is correlated with significantly higher bounce rates. Google uses CLS as a search ranking signal.

## Severity rationale

High because CLS above 0.1 is a failing Core Web Vitals score, degrades search ranking, and causes direct user errors from content jumping during interaction.

## Remediation

Declare explicit dimensions on every image and reserve space for dynamic content before it loads. Fix the three most common CLS sources:

1. Set `width` and `height` on images so the browser reserves space:
```tsx
// src/components/hero.tsx
<Image src="/hero.jpg" alt="Hero" width={1200} height={600} />
// or with plain img:
<img src="/hero.jpg" alt="Hero" style={{ aspectRatio: '2/1', width: '100%' }} />
```

2. Reserve space for ad or embed containers:
```html
<div style="min-height: 250px; min-width: 300px;"><!-- Ad slot --></div>
```

3. Set `font-display: swap` on all `@font-face` rules (see `ab-002009`) so font loading does not reflow text. Verify CLS in Chrome DevTools Performance tab — the Layout Shift rows in the experience lane identify every shift event with its contributing elements.

## Detection

- **ID:** `cls-fixed`
- **Severity:** `high`
- **What to look for:** Examine page layout for elements that shift during load: images without dimensions, late-loading content (ads, embeds), dynamic content insertion, or font swaps. Check CSS for rules that might cause shifts (width/height changes, margin/padding adjustments during transitions). Look for CSS containment usage or size attributes on media.
- **Pass criteria:** Images and media have explicit `width` and `height` attributes or aspect-ratio CSS set, preventing layout shifts. Ads or dynamic content containers have reserved space with `min-height`. Font loading uses `font-display: swap` to prevent FOIT/FOUT layout shifts.
- **Fail criteria:** Images loaded without dimensions causing layout shifts, late-loading content (ads, embeds) has no reserved space, or font swaps cause text reflow. Measured CLS exceeds 0.1.
- **Skip (N/A) when:** The project has no images, ads, or dynamic content that could cause shifts.
- **Detail on fail:** Identify the shift sources. Example: `"Hero image loads without dimensions; 150px downward shift. Ad container has no reserved height; shifts main content 200px when loaded. Font swap FOUT causes 30px text shift"` or `"Modal overlay toggled without fixed dimensions; shifts page during open/close"`.
- **Remediation:** Layout shifts are unexpected visual changes during page load. Prevent them by reserving space for dynamic content:

  1. Set image dimensions to prevent shifts:
     ```tsx
     <Image src="/hero.jpg" alt="Hero" width={1200} height={600} />
     // or with aspect-ratio CSS
     <img src="hero.jpg" alt="Hero" style={{ aspectRatio: '16/9' }} />
     ```

  2. Reserve space for ads and embeds:
     ```html
     <div style={{ minHeight: '250px' }}> {/* ad container */} </div>
     ```

  3. Use `font-display: swap` to prevent font-based shifts (see font loading check).

## External references

- iso-25010 performance-efficiency.time-behaviour

Taxons: performance

HTML version: https://auditbuffet.com/patterns/ab-002002
