# Images specify width and height to prevent layout shift

- **Pattern:** `ab-002054` (`performance-load.images.image-sizing`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002054
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002054)

## Why it matters

Images without explicit `width` and `height` attributes cause Cumulative Layout Shift (CLS), one of three Core Web Vitals metrics. When a browser downloads an image and discovers its dimensions, it reflows surrounding content — shifting text and buttons mid-read. Google's CWV assessment penalizes pages with CLS above 0.1, and users who experience unexpected layout shifts are significantly more likely to abandon a page. This is a direct business impact: form submissions and purchase buttons that shift away from the user's tap are missed conversions.

## Severity rationale

High because Cumulative Layout Shift caused by dimensionless images is a Core Web Vitals failure that directly harms search ranking and user retention.

## Remediation

Add `width` and `height` attributes to every `<img>` tag, or use `aspect-ratio` CSS on the container. For dynamically sized images, `aspect-ratio` preserves space without hardcoding pixel values. The Next.js `Image` component requires these attributes and handles the reservation automatically.

```tsx
// Before — layout shifts when image loads
<img src="/team.jpg" alt="Team" />

// After — space reserved before image loads
<img src="/team.jpg" alt="Team" width={800} height={600} />

// CSS aspect-ratio for fluid-width images
<div style={{ aspectRatio: '16/9', width: '100%' }}>
  <img src="/team.jpg" alt="Team" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
</div>

// Next.js Image (enforces dimensions)
import Image from 'next/image'
<Image src="/team.jpg" alt="Team" width={800} height={600} />
```

## Detection

- **ID:** `image-sizing`
- **Severity:** `high`
- **What to look for:** Count all `<img>` tags and Image components across the project. For each, check whether `width` and `height` attributes are present, or whether the `aspect-ratio` CSS property is applied to the container. These prevent Cumulative Layout Shift (CLS) by reserving space before images load. Flag any `width: 100%` usage without an explicit container aspect-ratio.
- **Pass criteria:** At least 90% of images have explicit `width` and `height` attributes or use the `aspect-ratio` CSS property to reserve space. No more than 1 image lacks dimension attributes. Next.js Image component always has width/height (required). Report: "X of Y images specify explicit dimensions or aspect-ratio."
- **Fail criteria:** 2 or more images lack width/height attributes, allowing the browser to discover dimensions only after loading, causing layout shift. Report: "X of Y images lack dimension attributes."
- **Skip (N/A) when:** No images detected in the project (0 `<img>` tags, 0 Image component usages found).
- **Detail on fail:** `"3 of 8 images lack width/height — Card.tsx, Hero.tsx, and Footer.tsx images have no dimension attributes"` or `"5 of 12 background images use width:100% without aspect-ratio, causing layout shift"`
- **Remediation:** Always provide dimensions:

  ```tsx
  // Before — layout shift risk
  <img src="/team.jpg" alt="Team" />

  // After — prevents layout shift
  <img src="/team.jpg" alt="Team" width={800} height={600} />

  // Next.js Image (width/height required)
  <Image src="/team.jpg" alt="Team" width={800} height={600} />

  // CSS aspect-ratio for dynamic images
  <img src="/image.jpg" style={{ aspectRatio: '16/9', width: '100%' }} />
  ```

## External references

- iso-25010 performance-efficiency.resource-utilization

Taxons: performance

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