Images are often the largest assets on a webpage and the main factor in Largest Contentful Paint (LCP). The Next.js Image component handles optimization automatically: it resizes images, serves modern formats, lazy loads by default, and prevents layout shift. Using it correctly can significantly improve Core Web Vitals.
How next/image works
When you use the Image component, Next.js:
- Generates multiple sizes of the image at build time or on-demand
- Serves WebP or AVIF when the browser supports them
- Lazy loads images below the fold
- Reserves space to prevent Cumulative Layout Shift (CLS)
| Feature | Benefit |
|---|---|
| Automatic resizing | Smaller file sizes for smaller screens |
| Modern formats | WebP is 25-35% smaller than JPEG; AVIF even smaller |
| Lazy loading | Images load only when approaching viewport |
| Aspect ratio reservation | No layout shift as images load |
Basic usage
Import the component and provide required props:
import Image from 'next/image';
export default function Hero() {
return (
<Image
src="/hero.jpg"
alt="Hero image showing a mountain landscape"
width={1200}
height={630}
/>
);
}
For local images, you can import them directly:
import Image from 'next/image';
import heroImage from '@/public/hero.jpg';
export default function Hero() {
return (
<Image
src={heroImage}
alt="Hero image"
// width and height are inferred from the import
/>
);
}
Remote images
For external images, add the domain to next.config.js:
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'images.unsplash.com',
},
{
protocol: 'https',
hostname: 'cdn.example.com',
pathname: '/images/**',
},
],
},
};
Then use the full URL:
<Image
src="https://images.unsplash.com/photo-123"
alt="Unsplash photo"
width={800}
height={600}
/>
The sizes prop
The sizes prop tells the browser how wide the image will be at different viewport widths. Without it, Next.js may generate and serve larger images than needed.
Common patterns
| Layout | sizes value |
|---|---|
| Full-width hero | 100vw |
| Half-width on desktop | (min-width: 768px) 50vw, 100vw |
| Fixed max-width card | (max-width: 768px) 100vw, 400px |
| Sidebar thumbnail | 200px |
Full example
<Image
src="/product.jpg"
alt="Product photo"
width={800}
height={800}
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 400px"
/>
This tells the browser:
- On screens up to 640px: image is 100% of viewport width
- On screens 641px to 1024px: image is 50% of viewport width
- On larger screens: image is 400px wide
The browser picks the smallest source that fits, reducing bandwidth.
Fill mode
For responsive images that fill their container, use fill instead of width/height:
<div className="relative h-64 w-full">
<Image
src="/banner.jpg"
alt="Banner"
fill
className="object-cover"
sizes="100vw"
/>
</div>
The parent must have position: relative (or absolute/fixed). The image fills the parent and you control fit with object-fit.
Priority and LCP
For the most important image on the page (usually the LCP element), add priority:
<Image
src="/hero.jpg"
alt="Hero"
width={1920}
height={1080}
priority
sizes="100vw"
/>
Priority:
- Disables lazy loading
- Adds a preload hint in the HTML head
- Ensures the image loads as fast as possible
Use priority on 1-2 images per page. Overusing it defeats the purpose and can hurt performance.
Blur placeholders
Placeholders improve perceived performance by showing something immediately while the full image loads.
Local images
For imported local images, Next.js generates blur data automatically:
import Image from 'next/image';
import photo from '@/public/photo.jpg';
<Image
src={photo}
alt="Photo"
placeholder="blur"
// blurDataURL is generated automatically
/>
Remote images
For remote images, provide your own blur data URL:
<Image
src="https://cdn.example.com/photo.jpg"
alt="Photo"
width={800}
height={600}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..."
/>
Generate blur hashes with tools like plaiceholder or a simple 10x10 resized version encoded as base64.
Quality setting
The default quality is 75, which balances file size and visual quality. Adjust per image:
<Image
src="/photo.jpg"
alt="High quality photo"
width={1200}
height={800}
quality={85}
/>
| Quality | Use case |
|---|---|
| 60-70 | Thumbnails, decorative images |
| 75 | Default, good for most images |
| 80-85 | Hero images, product photos |
| 90+ | Photography portfolios, print-quality |
Higher quality means larger files. Rarely go above 90.
Image formats
Next.js serves WebP by default when supported. You can enable AVIF:
// next.config.js
module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
},
};
AVIF offers better compression but takes longer to encode. For static sites with build-time optimization, this tradeoff is often worth it.
Responsive images with art direction
For different images at different breakpoints (not just sizes), use the <picture> element with regular <source> elements and an <img> fallback. Next.js Image handles one source; for art direction, you need native HTML:
<picture>
<source
media="(min-width: 768px)"
srcSet="/hero-desktop.jpg"
/>
<source
media="(min-width: 480px)"
srcSet="/hero-tablet.jpg"
/>
<img
src="/hero-mobile.jpg"
alt="Hero"
width={480}
height={320}
/>
</picture>
For most responsive needs, sizes with a single source is sufficient.
Common mistakes
| Mistake | Fix |
|---|---|
Missing alt |
Always provide descriptive alt text |
Missing sizes |
Set sizes to match actual rendered width |
| Priority on all images | Use only for above-fold LCP image |
| Wrong width/height | Use actual or desired display dimensions |
| fill without parent positioning | Parent needs position: relative |
| Huge quality values | Keep at 75-85 for most images |
Debugging image optimization
Check which image variant loads in DevTools Network tab. The URL includes size and format info:
/_next/image?url=%2Fhero.jpg&w=1920&q=75
Compare file sizes to verify optimization is working. WebP should be noticeably smaller than JPEG.
Static export limitations
If you use output: 'export' for static HTML, Next.js image optimization requires a server. Options:
- Use a third-party image CDN (Cloudinary, Imgix)
- Use
unoptimized: trueon images (loses optimization) - Deploy to a platform with image optimization (Vercel, Netlify)
Summary
The Next.js Image component automates image optimization with minimal configuration. Set sizes to match your layout, use priority for above-fold images, add placeholder="blur" for better perceived performance, and let Next.js handle resizing and format conversion. This combination typically reduces image weight by 40-60% and improves LCP scores significantly.
