Modern image optimization: formats (WebP, AVIF), responsive images, the Next.js Image component, lazy loading, and CDN strategies.
Modern image optimization: formats (WebP, AVIF), responsive images, the Next.js Image component, lazy loading, and CDN strategies.
BeforeMerge offers hundreds of code review rules, guides, and detection patterns to help your team ship better code.
Images are typically the largest assets on a web page. Optimizing them has the biggest impact on load time.
| Format | Compression | Browser Support | Best For |
|---|---|---|---|
| JPEG | Lossy | Universal | Photos |
| PNG | Lossless | Universal | Graphics with transparency |
| WebP | Both | 97%+ | General replacement for JPEG/PNG |
| AVIF | Both | 92%+ | Best compression, slower to encode |
| SVG | Vector | Universal | Icons, logos, illustrations |
Strategy: Serve AVIF with WebP fallback:
<picture>
<source srcset="hero.avif" type="image/avif">
<source srcset="hero.webp" type="image/webp">
<img src="hero.jpg" alt="Hero image" width="1200" height="600">
</picture>The next/image component handles optimization automatically:
import Image from "next/image";
// Static import (automatically sized)
import heroImg from "./hero.jpg";
<Image src={heroImg} alt="Hero" priority />
// Remote image (must specify dimensions)
<Image
src="https://cdn.example.com/photo.jpg"
alt="Photo"
width={800}
height={400}
sizes="(max-width: 768px) 100vw, 800px"
/>
// Fill parent container
<div className="relative h-64">
<Image src="/bg.jpg" alt="Background" fill className="object-cover" />
</div>Key props:
priority — Preload (use for above-the-fold images, disables lazy loading)sizes — Responsive size hints for correct srcset selectionquality — Compression quality (default 75, range 1-100)placeholder="blur" — Low-res placeholder while loadingServe different sizes based on viewport:
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 75vw, 1200px"
/>This generates a srcset with multiple sizes. The browser picks the best one.
Images below the fold should load lazily:
<!-- Native lazy loading -->
<img src="photo.jpg" loading="lazy" alt="Photo">next/image lazy loads by default (unless priority is set).
Always specify dimensions to prevent CLS:
// Good — explicit dimensions
<Image src="/photo.jpg" width={800} height={400} alt="Photo" />
// Good — fill mode with sized container
<div style={{ position: "relative", width: "100%", aspectRatio: "16/9" }}>
<Image src="/photo.jpg" fill alt="Photo" />
</div>
// Bad — no dimensions, causes layout shift
<img src="/photo.jpg" alt="Photo" />const cloudinaryLoader = ({ src, width, quality }: ImageLoaderProps) => {
return `https://res.cloudinary.com/demo/image/upload/w_${width},q_${quality || 75}/${src}`;
};
<Image loader={cloudinaryLoader} src="photo.jpg" width={800} height={400} alt="Photo" />priority only for above-the-fold imagessizes attribute for responsive images