Image Optimization
Next.js provides automatic image optimization through the next/image component. It's one of the biggest performance wins you can get.
The Problem with Regular Images
// ❌ Problems with <img>:
// - No lazy loading by default
// - No responsive sizes
// - No format optimization (WebP/AVIF)
// - Causes layout shift (CLS)
<img src="/hero.jpg" alt="Hero" />
The next/image Component
import Image from 'next/image'
export default function Hero() {
return (
<Image
src="/hero.jpg"
alt="Hero image"
width={1200}
height={600}
priority // Load immediately (above the fold)
/>
)
}
What Next.js does automatically:
- Converts to WebP/AVIF (smaller files)
- Resizes for device screen
- Lazy loads by default
- Prevents layout shift
Sizing Images
Fixed Size
<Image
src="/avatar.jpg"
alt="User avatar"
width={64}
height={64}
/>
Fill Container
<div className="relative h-64 w-full">
<Image
src="/banner.jpg"
alt="Banner"
fill
className="object-cover"
/>
</div>
Note: Parent must have position: relative and defined dimensions.
Responsive Images
Use sizes to tell the browser how large the image will be:
<Image
src="/hero.jpg"
alt="Hero"
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
This generates appropriate srcset entries. Without sizes, Next.js can't optimize effectively.
| Viewport | Image Width |
|---|---|
| < 768px | 100% of viewport |
| < 1200px | 50% of viewport |
| > 1200px | 33% of viewport |
Priority Loading
Use priority for above-the-fold images:
// ✅ LCP image - load immediately
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
priority
/>
// Below the fold - lazy load (default)
<Image
src="/product.jpg"
alt="Product"
width={400}
height={400}
/>
Remote Images
Configure allowed domains in next.config.js:
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'images.unsplash.com',
},
{
protocol: 'https',
hostname: '*.cloudinary.com',
},
],
},
}
<Image
src="https://images.unsplash.com/photo-123"
alt="Unsplash image"
width={800}
height={600}
/>
Placeholder Blur
Show a blur while loading:
// Local images - automatic blur data
import heroImage from '@/public/hero.jpg'
<Image
src={heroImage}
alt="Hero"
placeholder="blur"
/>
// Remote images - provide blur data URL
<Image
src="https://example.com/image.jpg"
alt="Remote"
width={800}
height={600}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..."
/>
Common Patterns
Card with Image
function ProductCard({ product }) {
return (
<div className="relative aspect-square overflow-hidden rounded-lg">
<Image
src={product.image}
alt={product.name}
fill
sizes="(max-width: 768px) 50vw, 25vw"
className="object-cover hover:scale-105 transition-transform"
/>
</div>
)
}
Avatar
function Avatar({ user, size = 40 }) {
return (
<Image
src={user.avatar || '/default-avatar.png'}
alt={user.name}
width={size}
height={size}
className="rounded-full"
/>
)
}
Summary
- Use
next/imagefor automatic optimization - Set
widthandheightOR usefillwith sized parent - Use
priorityfor above-the-fold images - Add
sizesfor responsive images - Configure
remotePatternsfor external images - Use
placeholder="blur"for better loading UX

