# Responsive images with srcset and sizes

- **Pattern:** `ab-002008` (`performance-core.image-media-optimization.responsive-images`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002008
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002008)

## Why it matters

A 2400-pixel-wide hero image served to a 375-pixel mobile viewport transfers 1.2 MB to display roughly 110 KB of visual information (ISO-25010 resource-utilisation). Without `srcset` and `sizes`, the browser has no signal to choose a smaller variant — it downloads the full-resolution image regardless of device. Multiply that across ten images on a product page and mobile users are downloading 10x the pixels they can display, with proportional impact on page weight, LCP, and data cost.

## Severity rationale

Medium because absent `srcset`/`sizes` causes mobile devices to download full-resolution images they cannot fully display, wasting significant bandwidth on every visit.

## Remediation

Add `srcset` with width variants and `sizes` that match your actual layout breakpoints:

```html
<img
  src="/images/product-600w.jpg"
  srcset="/images/product-300w.jpg 300w,
          /images/product-600w.jpg 600w,
          /images/product-1200w.jpg 1200w"
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 600px"
  alt="Product"
  width="600"
  height="400"
/>
```

With Next.js, provide a `sizes` prop and the framework generates `srcset` automatically:
```tsx
<Image
  src="/images/product.jpg"
  alt="Product"
  width={600}
  height={400}
  sizes="(max-width: 768px) 100vw, 50vw"
/>
```

The `sizes` value must reflect the actual rendered width, not just viewport width — an image in a two-column grid at 1200px is 50vw, not 100vw.

## Detection

- **ID:** `responsive-images`
- **Severity:** `medium`
- **What to look for:** Check `<img>` tags for `srcset` and `sizes` attributes, or next/image usage with breakpoints. Look for image variants at different resolutions (1x, 2x, or width-based srcset). Verify sizes attribute matches layout (e.g., `sizes="(max-width: 768px) 100vw, 50vw"`).
- **Pass criteria:** Images use `srcset` with multiple resolution variants (at minimum 1x and 2x), and `sizes` attribute reflects actual layout. Or next/image is used with responsive width handling. Users on low-bandwidth connections and smaller devices receive appropriately sized images.
- **Fail criteria:** No srcset or sizes attributes; same image served to all devices regardless of viewport width or device pixel ratio. High-resolution images served to mobile devices unnecessarily.
- **Skip (N/A) when:** All images are small (under 100KB) or the same aspect ratio on all viewports.
- **Detail on fail:** Specify the responsive design gaps. Example: `"Hero image 2400px wide always served; mobile users download 1.2MB image for 375px viewport. No srcset or responsive handling"` or `"srcset present but sizes attribute missing; browser can't choose optimal image"`.
- **Remediation:** Responsive images match device capabilities and layout:

  ```html
  <img
    src="image-600w.jpg"
    srcset="image-300w.jpg 300w, image-600w.jpg 600w, image-1200w.jpg 1200w"
    sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 800px"
    alt="Image"
  />
  ```

  Or with Next.js (handles automatically):
  ```tsx
  <Image
    src="/image.jpg"
    alt="Image"
    width={600}
    height={400}
    sizes="(max-width: 768px) 100vw, 50vw"
  />
  ```

## External references

- iso-25010 performance-efficiency.resource-utilization

Taxons: performance

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