# Below-fold images use lazy loading

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

## Why it matters

Eagerly loading below-fold images forces users to download content they may never scroll to — consuming bandwidth, extending Time to Interactive, and degrading performance on mobile or metered connections. On pages with galleries, comment sections, or long lists of testimonials, below-fold images can represent 60–80% of total image payload. This wasted transfer directly increases LCP for above-fold content, since the browser competes for bandwidth across all eager loads. ISO 25010 performance-efficiency.time-behaviour captures this as unnecessary resource acquisition that delays the user's first meaningful interaction.

## Severity rationale

Medium because below-fold eager loading wastes bandwidth and increases LCP indirectly, but does not prevent the page from being usable once loaded.

## Remediation

Add `loading="lazy"` to all `<img>` tags that appear below the first major content section. Above-fold images — hero, logo, header — should remain eager or use `priority` in Next.js Image to avoid delayed LCP. The Next.js `Image` component applies lazy loading by default unless `priority` is set.

```tsx
// Above-fold — load immediately
<img src="/hero.jpg" alt="Hero" width={1200} height={630} />

// Below-fold — defer until near viewport
<img src="/testimonial.jpg" alt="Jane" width={200} height={200} loading="lazy" />

// Next.js: lazy by default, priority for above-fold
import Image from 'next/image'
<Image src="/hero.jpg" alt="Hero" width={1200} height={630} priority />
<Image src="/card.jpg" alt="Card" width={400} height={300} /> {/* lazy by default */}

// Heavy galleries — defer the entire component
const Gallery = dynamic(() => import('./Gallery'), { loading: () => <Skeleton /> })
```

## Detection

- **ID:** `lazy-loading`
- **Severity:** `medium`
- **What to look for:** Count all `<img>` tags and Image components that appear below the fold (after the first major page section). For each, classify as: (a) has `loading="lazy"`, (b) uses a framework component with default lazy loading (Next.js Image), (c) uses a JS lazy loading library, or (d) lacks any lazy loading. Since fold position cannot be determined from static code analysis, apply this heuristic: Images in the first component/section of a page (hero images, header logos) are considered above-the-fold and should NOT have `loading="lazy"` (or should use `priority` in Next.js Image). All other images below the first major content section should have `loading="lazy"`. The Next.js Image component uses lazy loading by default — this passes. Plain `<img>` tags after the first major content section without `loading="lazy"` fail.
- **Pass criteria:** At least 90% of below-fold images use `loading="lazy"`, or a framework image component applies lazy loading by default, or a JavaScript lazy loading library is in use. No more than 1 below-fold plain `<img>` tag lacks lazy loading. Report: "X of Y below-fold images use lazy loading."
- **Fail criteria:** 2 or more plain `<img>` tags for non-hero content after the first major section lack `loading="lazy"` and no lazy loading library is detected.
- **Skip (N/A) when:** All images are in the first/hero section of the page (0 below-fold images), or lazy loading is handled by the framework automatically for all images, or no images detected in the project.
- **Detail on fail:** `"4 of 6 below-fold images lack loading='lazy' — comments section, testimonials, and footer images loaded eagerly"` or `"0 of 8 gallery images below the fold have lazy loading configured"`
- **Remediation:** Lazy load off-screen images:

  ```tsx
  // Before — loads all images on page load
  <img src="/team.jpg" alt="Team" />

  // After — loads only when visible
  <img src="/team.jpg" alt="Team" loading="lazy" />

  // Next.js Image with lazy loading
  <Image src="/team.jpg" alt="Team" width={800} height={600} />
  {/* Default behavior is lazy except with priority prop */}

  // Dynamic import for heavy image galleries
  const LazyGallery = dynamic(() => import('./Gallery'), { loading: () => <Skeleton /> })
  ```
- **Cross-reference:** For image alt text and accessibility concerns with lazy-loaded images, the Accessibility Fundamentals audit covers image accessibility in detail.

## External references

- iso-25010 performance-efficiency.time-behaviour

Taxons: performance

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