# Images are not significantly larger than their display size

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

## Why it matters

A product card image with 2000px intrinsic width displayed at 400px wastes 97% of the downloaded pixels and commonly adds 400KB–2MB of avoidable payload. Multiply this across a catalog page with 12 products and users are downloading 5–24MB of image data that serves no visual purpose. Beyond raw bandwidth, the browser must decode every pixel before painting — a CPU-intensive operation that extends Time to Interactive and drains mobile batteries. ISO 25010 performance-efficiency.resource-utilization classifies this pattern as disproportionate resource consumption relative to the output produced.

## Severity rationale

Low because oversized images hurt performance without breaking functionality, but the cumulative payload cost is significant on image-heavy pages.

## Remediation

Resize image files to match their largest display size (no more than 2x for high-DPI screens). Use an image optimization service at build time or serve through a CDN that resizes on demand. The Next.js `Image` component auto-resizes via Vercel's image optimization pipeline.

```tsx
// Before — 2000px image displayed at 400px
<img src="/product-original.jpg" style={{ width: '400px' }} />

// After — correctly sized source
<img src="/product-400w.jpg" style={{ width: '400px' }} />

// Next.js — auto-resizes to the width you specify
import Image from 'next/image'
<Image src="/product.jpg" alt="Product" width={400} height={300} />
// Vercel delivers a 400×300 optimized image, not the raw file

// Build-time resize with Sharp
// scripts/optimize-images.ts
import sharp from 'sharp'
await sharp('public/product-original.jpg')
  .resize(400, 300, { fit: 'cover' })
  .webp({ quality: 82 })
  .toFile('public/product-400w.webp')
```

## Detection

- **ID:** `no-oversized-images`
- **Severity:** `low`
- **What to look for:** Count all content images and compare each image's intrinsic dimensions (or file size if dimensions unavailable) to its CSS/HTML display size. For each image, calculate the ratio: intrinsic width / display width. Enumerate: "X of Y images are appropriately sized (ratio under 2x)."
- **Pass criteria:** No more than 1 image has an intrinsic-to-display ratio exceeding 2x. At least 80% of images are within 50% of their display size. No single image file exceeds 500KB unless it is a full-bleed hero displayed at viewport width. Report even on pass: "X of Y images sized within 2x of display dimensions."
- **Fail criteria:** 2 or more image files have intrinsic dimensions more than 2x larger than their display size, or any single image exceeds 1MB while displayed at under 800px wide.
- **Skip (N/A) when:** No images detected in the project (0 `<img>` tags and 0 CSS background images found).
- **Detail on fail:** `"3 of 6 images are oversized — product card images are 2000px wide but display at 400px (5x ratio), testimonial avatar is 1200px for a 64px display"` or `"Background image is 4MB JPG but displays at 400x300px — 10x larger than needed"`
- **Remediation:** Resize images to match display context:

  ```tsx
  // Before — oversized
  <img src="/product-2000px.jpg" style={{ width: '400px' }} />

  // After — appropriately sized
  <img src="/product-400px.jpg" style={{ width: '400px' }} />

  // Use image optimization services (Vercel, Cloudinary, imgix) to auto-resize
  <Image src="/product.jpg" alt="Product" width={400} height={300} />
  ```

---

## External references

- iso-25010 performance-efficiency.resource-utilization

Taxons: performance

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