Short answer: To optimize Next.js images for performance, use the built-in next/image component, which automatically serves responsive images, lazy loads them, and converts to modern formats like WebP. Configure remote URLs in next.config.js, set appropriate sizes, and use priority for above-the-fold images.
Key takeaways
- Always use next/image for automatic optimization.
- Enable lazy loading for all images by default.
- Configure remote hostnames in next.config.js.
- Set explicit width and height to prevent layout shifts.
- Use priority for above-the-fold images.
- Serve modern formats like WebP and AVIF.
What you will find here
- Why Image Optimization Matters in Next.js
- Getting Started with next/image
- How Lazy Loading Improves Performance
- Setting Responsive Sizes and Breakpoints
- Using Priority for Above-the-Fold Images
- Comparing Image Formats: JPEG vs WebP vs AVIF
- Additional Optimization Techniques
- Common Mistakes to Avoid
- How to Debug Image Optimization Issues
- Optimizing for Different Screen Sizes and Devices
Images are often the heaviest assets on a web page. In Next.js, you can optimize images for performance using the built-in next/image component. This component automatically applies lazy loading, responsive sizing, and modern image formats. In this article, you will learn practical steps to optimize Next.js images and improve your site’s speed and user experience.
Why Image Optimization Matters in Next.js
Large images slow down page load times and hurt Core Web Vitals, especially Largest Contentful Paint (LCP). Next.js provides the next/image component to handle optimization automatically. It resizes images, serves them in next-gen formats like WebP and AVIF, and lazy loads them by default. This reduces bandwidth usage and improves performance.
Without optimization, a 2 MB hero image can delay your LCP by several seconds. With next/image, the same image can be served as a 200 KB WebP file, dramatically improving load time.

Getting Started with next/image
To use the component, import Image from next/image. You can use it for local images stored in your project or remote images from external URLs.
Using with Local Images
For local images, just import the file and pass it to the src prop. Next.js automatically optimizes these images.
import Image from 'next/image';
import heroImage from '../public/hero.jpg';
export default function Page() {
return (
<Image
src={heroImage}
alt="Hero image"
width={1200}
height={600}
/>
);
}
Using with Remote Images
For remote images, you need to configure the allowed hostnames in next.config.js. This is a security measure.
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
port: '',
pathname: '/images/**',
},
],
},
};
Then you can use the remote URL in the src prop. Note that you must provide width and height to prevent layout shifts.
How Lazy Loading Improves Performance
The next/image component lazy loads images by default. This means images are only loaded when they enter the viewport, saving bandwidth on initial page load. For above-the-fold images, you can disable lazy loading using the priority prop.
Lazy loading is implemented using the native loading="lazy" attribute and Intersection Observer. It ensures that below-fold images do not block the initial render.
Setting Responsive Sizes and Breakpoints
To serve the right image size for each device, use the sizes and fill props. The sizes prop tells the browser how large the image will be at different breakpoints, helping select the best source.
<Image
src="/hero.jpg"
alt="Hero"
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
The fill prop makes the image fill its parent container. You must set the parent to position: relative and define its size.

Using Priority for Above-the-Fold Images
The priority prop tells Next.js to preload the image and skip lazy loading. Use it for the largest above-the-fold image, usually the hero image. This improves LCP because the image starts loading immediately.
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
priority
/>
Only use priority for one or two images to avoid overwhelming the network.
Comparing Image Formats: JPEG vs WebP vs AVIF
Modern formats like WebP and AVIF provide better compression than JPEG. Next.js automatically negotiates the format based on the browser’s Accept header. You can control this with the formats configuration.
| Format | Compression | Browser Support | Recommended Use |
|---|---|---|---|
| JPEG | Good | All | Fallback |
| WebP | Better | Widely supported | Primary format |
| AVIF | Best | Supported in many modern browsers | For supported browsers |
By default, Next.js offers WebP and AVIF. You can customize the allowed formats in next.config.js.
Additional Optimization Techniques
Image Caching and CDN
Next.js caches optimized images in the .next/cache/images directory. For production, consider using a CDN to serve images with cache headers. You can configure custom image loaders to use a CDN like Cloudinary or Imgix.
Blur Up and Placeholder
The placeholder prop allows you to show a blurred version of the image while it loads. This improves perceived performance. Use blur for local images or data URL for remote images.
<Image
src={heroImage}
alt="Hero"
placeholder="blur"
/>
Common Mistakes to Avoid
Many developers forget to configure remotePatterns for external images, causing errors. Others omit width and height, leading to layout shifts. Avoid using large images without setting sizes, as the browser may download oversized images. Also, do not apply priority to every image; it defeats lazy loading.
Always test your images with Lighthouse to verify optimization. Check the “Properly size images” audit to see if you serve correctly sized images.
How to Debug Image Optimization Issues
When images don’t look right or performance isn’t improving, you can debug using Next.js’s built-in image optimization endpoint. Check the URL of the optimized image: it usually has /_next/image?url=.... If the image is not being optimized, ensure you are using the Image component and not a regular <img> tag. For remote images, verify that the hostname is in remotePatterns and that the image URL is accessible. Use the browser’s network tab to inspect the image request and response headers. Look for content-type to confirm it’s WebP or AVIF. Also check the response status — a 404 means the URL is wrong or the image doesn’t exist.
Another common issue is that the image size doesn’t match the layout. Use the onLoadingComplete callback to get the actual image dimensions and compare them with what you expect. This helps identify if sizes or width and height are misconfigured.
Optimizing for Different Screen Sizes and Devices
To deliver the best experience across mobile, tablet, and desktop, combine the sizes prop with CSS media queries. The sizes attribute tells the browser what width the image will display at each breakpoint. For example, for a full-width hero on mobile and a half-width image on desktop, use sizes="(max-width: 768px) 100vw, 50vw". Always test on real devices to confirm the correct image is downloaded. You can check the image’s “current src” in the browser’s inspector to see which URL the browser selected. If it picks a too-large image, your sizes attribute might be too broad.
Remember that the Image component generates multiple resized versions of each source image. The default device sizes are: 640, 750, 828, 1080, 1200, 1920, 2048, and 3840 pixels. You can customize these in next.config.js with the imageSizes and deviceSizes options. Adjust them based on your breakpoints and the maximum width of your layout.
Frequently asked questions
Does next/image automatically convert images to WebP?
Yes, the next/image component automatically serves images in WebP and AVIF formats when the browser supports them. It negotiates the format based on the Accept header, so you don’t need to manually convert images.
Do I need to set width and height for all next/images?
Yes, you should always set width and height to prevent layout shifts and improve Cumulative Layout Shift (CLS). The only exception is when using the fill prop, where the parent container defines the dimensions.
How do I use next/image with images from a CMS?
You can use the remote image approach: configure the CMS domain in remotePatterns in next.config.js, then pass the image URL to the src prop. Ensure you provide width, height, and alt text.
Can I use next/image with SVG files?
Yes, but the next/image component does not optimize SVGs because they are vector-based. It will pass the SVG through without resizing or converting formats. You can use an tag or inline instead.
What is the priority prop and when should I use it?
The priority prop tells Next.js to preload the image and skip lazy loading. Use it for the largest above-the-fold image (usually the hero) to improve LCP. Avoid using it on multiple images to prevent unnecessary bandwidth usage.

Leave a Reply