# Images use lazy loading

- **Pattern:** `ab-002540` (`site-health-check.performance-signals.lazy-loading`)
- **Severity:** info
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002540
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002540)

## Why it matters

Images are typically the largest assets on a page. Without lazy loading, every image below the fold downloads on initial page load — including images the user may never scroll to. On an image-heavy page, this can add multiple megabytes to the initial payload, directly increasing Time to Interactive. ISO 25010 performance-efficiency applies: loading offscreen resources wastes bandwidth and delays rendering of visible content. The `loading='lazy'` attribute is a native browser feature with no JavaScript dependency, universally supported in modern browsers, and requires zero additional infrastructure to use.

## Severity rationale

Info because the performance cost depends on image count and sizes — pages with few or small images see negligible impact, making this an optimization opportunity rather than a guaranteed defect.

## Remediation

Add `loading="lazy"` to images that appear below the fold. This is a single attribute change with no JavaScript required:

```html
<!-- Below-the-fold images — lazy load -->
<img src="feature.jpg" alt="Feature diagram" loading="lazy" width="800" height="600">

<!-- Hero/above-the-fold image — do NOT lazy load -->
<img src="hero.jpg" alt="Hero" loading="eager">
```

In Next.js, the `<Image>` component applies lazy loading by default — `loading="eager"` must be set explicitly for the hero. For responsive sizing, add `srcset` and `sizes` to avoid serving oversized images to small viewports. The `width` and `height` attributes prevent layout shift (CLS) by reserving space before the image loads.

## Detection

- **ID:** `lazy-loading`
- **Severity:** `info`
- **What to look for:** Count the total number of `<img>` tags in the HTML. For each `<img>` tag, check for the presence of `loading="lazy"` attribute or `srcset` attribute. Count how many images have at least 1 of these optimization attributes. Calculate the percentage of optimized images.
- **Pass criteria:** At least 1 `<img>` tag has `loading="lazy"` or `srcset`, OR the page has 0 `<img>` tags (no images to optimize). If images are present, at least 50% of below-the-fold images should use lazy loading. Report: "X of Y images use loading='lazy' or srcset."
- **Fail criteria:** The page has 1 or more `<img>` tags, but 0 of them use `loading="lazy"` or `srcset` attributes.
- **Skip (N/A) when:** The page contains 0 `<img>` tags in the HTML (nothing to evaluate).
- **Error when:** SPA detected.
- **Detail on fail:** `"Found 8 images, none using loading='lazy' or srcset"`
- **Remediation:** Lazy loading defers offscreen image downloads until users scroll to them, reducing initial page weight. Add `loading="lazy"` to images below the fold:

  ```html
  <img src="photo.jpg" alt="Description" loading="lazy" width="800" height="600">
  ```

  In Next.js, the `<Image>` component applies lazy loading by default. For responsive images, add `srcset`: `<img srcset="small.jpg 400w, large.jpg 800w" sizes="(max-width: 600px) 400px, 800px">`. Do NOT lazy-load the hero/above-the-fold image — it should load eagerly.

## External references

- iso-25010 performance-efficiency.resource-utilization

Taxons: performance

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