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.
Low because oversized images hurt performance without breaking functionality, but the cumulative payload cost is significant on image-heavy pages.
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.
// 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')
ID: performance-load.images.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:
// 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} />