Image Optimization (next/image) in Next.js
The Image component from next/image automatically optimizes images: converts to modern formats, picks the right size for the device and loads lazily.
Why Not a Regular img
A regular <img> loads the original image entirely regardless of screen size. On a mobile device the same 2000px image loads as on desktop. The Image component solves this problem.
Basic Usage
import Image from 'next/image'
export default function ProblemCard() {
return (
<Image
src="/images/problem-preview.png"
alt="Problem preview on Hack Frontend"
width={800}
height={400}
/>
)
}
What Image Does Under the Hood
Format conversion
Automatically converts to WebP or AVIF if the browser supports them. This reduces file size by 30-50%.
Device-based resizing
Generates multiple image variants of different sizes. The browser downloads only the appropriate one.
Lazy loading
By default images load lazily: only when they enter the viewport. This speeds up initial page load.
CLS prevention
Reserves space for the image before it loads, preventing Cumulative Layout Shift.
Local Images
For local files Next.js determines dimensions automatically:
import Image from 'next/image'
import banner from '@/public/images/HackFrontendBanner.png'
export default function Hero() {
return (
<Image
src={banner}
alt="Hack Frontend"
placeholder="blur"
/>
)
}
placeholder="blur" shows a blurred preview before loading. For local images the blur placeholder is generated automatically.
Filling a Container (fill)
When dimensions are not known in advance:
<div className="relative h-64 w-full">
<Image
src={user.avatar}
alt={user.name}
fill
className="object-cover rounded-lg"
sizes="(max-width: 768px) 100vw, 50vw"
/>
</div>
The fill property stretches the image to fill its parent container. sizes hints the browser which variant to download.
The priority Property
For above-the-fold images visible immediately:
<Image
src="/images/hero.png"
alt="Hero"
width={1200}
height={600}
priority
/>
priority disables lazy loading and adds a preload hint. Use only for LCP images (1-2 per page).
External Images
For external URLs you need to configure domains in next.config.js:
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'avatars.githubusercontent.com'
},
{
protocol: 'https',
hostname: 'images.unsplash.com'
}
]
}
}
Security:
Always specify exact domains in remotePatterns. Open access to all domains creates abuse risk through the image optimization API.
Useful Resources
- nextjs.org/docs — Image Optimization
- Image API Reference