Image Optimization Guide
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>
Next.js Image Component
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 selection
quality — Compression quality (default 75, range 1-100)
placeholder="blur" — Low-res placeholder while loading
Responsive Images
Serve 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.
Lazy Loading
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).
Sizing Rules
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" />
CDN Strategies
Image CDN Services
- Cloudinary — Transform, optimize, deliver
- imgix — URL-based transformations
- Vercel Image Optimization — Built into Next.js on Vercel
Custom loader for external CDN:
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" />
Optimization Checklist