How to use the Next.js Image component to optimize images
Written by Adebiyi Adedotun✏️ The Next Image Component is the built-in image optimization solution for Next.js. It extends the native HTML element with built-in features for automatic image optimization. Image offers image optimization features such as automatic image compression, resizing, caching, and converting images to more efficient formats like WebP where possible. These features significantly improve the user and developer experience. By default, the Next.js default image optimization API will optimize and serve your images from the Next.js server. However, you can opt out of this default behavior and use other image optimization solutions such as Fastly Image Optimizer. Therefore, the Next.js Image Component is not only feature-rich but flexible as well. In this article, we’ll explore automatic image optimization using the Next.js built-in Image component. An introduction to Next Image A picture is worth a thousand words, and images are an important part of the web for communicating with users. Defining them in their most basic form is straightforward using the HTML element: You can add an alternative text (alt) to describe the image for screen readers or if the browser fails to load it:

Written by Adebiyi Adedotun✏️
The Next Image
Component is the built-in image optimization solution for Next.js. It extends the native HTML
element with built-in features for automatic image optimization. Image
offers image optimization features such as automatic image compression, resizing, caching, and converting images to more efficient formats like WebP where possible.
These features significantly improve the user and developer experience. By default, the Next.js default image optimization API will optimize and serve your images from the Next.js server.
However, you can opt out of this default behavior and use other image optimization solutions such as Fastly Image Optimizer. Therefore, the Next.js Image Component is not only feature-rich but flexible as well. In this article, we’ll explore automatic image optimization using the Next.js built-in Image
component.
An introduction to Next Image
A picture is worth a thousand words, and images are an important part of the web for communicating with users. Defining them in their most basic form is straightforward using the HTML
element:
src="image.jpg">
You can add an alternative text (alt
) to describe the image for screen readers or if the browser fails to load it:
src="image.jpg alt="describe the image here"/>
But with images on the web, the devil is in the details. To improve user and developer experience, there is a need for automatic image optimization. To serve the most optimal image efficiently, you need to focus on the image size, format, and responsiveness. This may be easy when dealing with static images such as icons.
However, some images, such as profile photos, are uploaded dynamically by users at runtime. Without automatic image optimization, it becomes impossible to serve such images efficiently.
Editor’s note: This post was updated by Joseph Mawa in April 2025 to reflect the latest updates in Next.js version 15 and add modern alternatives to next/image
.
The case for automatic image optimization using the Next.js Image
component
Frameworks like Next.js offer an abstraction that solves the most common, mundane, and complex tasks like routing, internationalization, and image optimization. According to the Next.js team, the goal of Next.js is to improve two things: the developer and user experiences.
While most of the optimization focuses on reducing the amount of JavaScript shipped to users, there are other resources, like images, that need optimization as well. Enter Next.js 10. Vercel, the company behind Next.js, released Next.js version 10 with a built-in image component, next/image
, for automatic image optimization, providing five benefits.
Improved user experience
With optimized images that are loaded lazily by default, users can expect a performance boost in website load time, ultimately improving the overall user experience.
Good developer experience
With next/image
’s simple-to-use API, developers have an improved experience themselves with the ability to define a basic image, tweak it to their requirements, or delve into advanced configuration options like caching and loaders.
Unaffected build times
Build times aren’t increased as a side-effect of optimization. Next.js optimizes images on demand as users request them, instead of at build time.
Modern image techniques and formats
Images are lazy loaded by default and can be served in modern formats like WebP in supported web browsers.
Future proof
Next.js can also automatically adopt future image formats and serve them to browsers that support those formats.
Optimizing images using the Next.js Image
Component
The built-in next/image
API is the sweet spot for image optimization. It exposes an Image
component as a single source of truth. This means you only need to learn how to use one API to handle image optimization in Next.js. In its most basic form, the built-in Next.js image component is similar to the HTML
element. They both accept src
and alt
attributes:
import Image from "next/image";
export default function CardImage({ imageSrc, imageAltText }) {
return (
<div classname="cardImageWrapper">
<Image src={imageSrc} alt={imageAltText} />
</div>
);
}
The Image
component accepts several other props. Some are required while others are optional. The src
, width
, height
, and alt
props are required. The others are optional. Some of the optional props are used for customizing the default behavior of the Image
component. Let’s explore some of the Next.js built-in image optimization features.
Responsive images in Next.js
The devices we use have varying viewport widths, screen sizes, and resolutions. With the Next.js image component, you can use the sizes
prop to specify the image width at different breakpoints. The value of the sizes
prop is a string similar to a CSS media query:
<Image
fill
src="/example.png"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>;
>```
Next.js will use the `sizes` prop with the `deviceSizes` and `imageSizes` props that are configured in the `next.config` file to generate your image `srcset`s. The browser will then select and fetch the appropriate image based on the user’s viewport width, screen size, and resolution. If you don’t configure the device and image sizes yourself, Next.js will use the default values below. The default values are usually sufficient. You don’t need to modify them:
```javascript
module.exports = {
images: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
},
}
Using efficient image formats like WebP
Images make up a significant proportion of resources on the web. They come in different sizes and formats. Some image formats are more efficient than others. By default, Next.js converts images to WebP format in web browsers that support it.
This is because WebP images have smaller file sizes than other formats like JPG and PNG. Similarly, a compressed WebP image retains a higher quality than other image formats. You can configure the default image format using the next.config.js
file, like in the code below. The default format is image/webp
if you don’t specify your own:
module.exports = {
images: {
formats: ['image/avif'],
},
}
Next.js automatic image compression
Next.js has a built-in feature for automatic image compression. It compresses the image to reduce the size of the image file. Smaller images lead to reduced bandwidth usage and faster page load. You can use the quality
prop to specify the quality of the compressed image. The value of the quality
prop should be an integer from 1
to 100
. It defines the quality of the compressed image; 1
being the lowest quality and 100
being the highest. It defaults to 75
:
<Image src="image-src" alt="image-alt-text" quality={100} layout="fill" />;
You can also use the next.config.js
file to specify the qualities you want instead of allowing all the qualities from 1
to 100
. As an example, the configuration below allows only three qualities: 30
, 50
, and 70
:
module.exports = {
images: {
qualities: [30, 50, 70],
},
}
>```
If the `quality` you pass to the `Image` component is not one of the values you specified in the `qualities` array in the `next.config.js` file, you will get an HTTP response of `400(Bad Request)`.
### Lazy loading images in Next.js
Similar to the HTML `<img>` element, the `next/image` component has the `loading` property you can use to specify when the browser should load an image. Unlike in the HTML `<img>` element where the `loading` attribute defaults to `eager`, in the Next.js image component, it defaults to `lazy`. If you want the default, you can omit the attribute instead of explicitly setting it like so:
```javascript
<Image src="image-src" alt="image-alt-text" layout="fill" loading="lazy" />;
>```
If the `loading` property is set to `lazy`, the browser defers loading off-screen images until the user is about to scroll them into view. Lazy loading images results in faster initial page load, reduced bandwidth usage, and overall improvement in user experience.
### Image priority loading in Next.js
Next.js recommends that you lazy load off-screen images for reduced initial page load time and bandwidth usage. On the other hand, you need to preload images that are above the fold for improved performance. The built-in `next/image` component has the `priority` prop for doing just that.
If you set the value of the `priority` prop to `true`, the image is considered high-priority. Therefore, the browser will load it as early as possible. Using this property to preload above-the-fold images, such as icons and [hero images](https://blog.logrocket.com/ux-design/what-is-website-hero-section/), will improve the load time of your web page or app:
```javascript
<Image
src="image-src"
alt="image-alt-text"
width={500}
height={300}
priority
/>;
You need to be aware that setting priority
of an image to true
will automatically disable lazy loading. Similarly, you shouldn’t use the priority prop on lazy-loaded images.
Display Next.js placeholder image
Despite all the built-in image optimization techniques highlighted above, most images take longer to load than other static assets. Therefore, to reduce cumulative layout shift and provide a better user experience, it is necessary to display a placeholder image while an image is still loading.
You can use the placeholder
property to specify a fallback image while an image is loading. Its possible values are blur
, empty
, and data:image/
. It defaults to empty
, and when it is empty
, there is no placeholder while the image is loading — only an empty space:
<Image
placeholder="blur"
quality={100}
/>;
Optimized image caching in Next.js
By default, Next.js dynamically optimizes images on request and caches them in the
directory.
It will reuse the optimized image until the cache expires. Next.js uses the Cache-Control
header or minimumCacheTTL
configuration option, depending on whichever is larger, to determine the maximum age of the cached image. You can use the next.config.js
object to change the default time-to-live (TTL) for cached optimized images like so:
module.exports = {
images: {
minimumCacheTTL: 120, // 120 seconds
},
}
If you don’t specify a custom value as in the code above, Next.js will use the default value of 60 seconds. For Static image import, Next.js will hash the file contents and cache the file forever. Keep in mind that static imports can be disabled:
js
module.exports = {
images: {
disableStaticImages: true,
},
};
The Next.js docs have a detailed explanation of the default caching behavior. However, if you use a different loader, like Cloudinary, you must refer to its documentation to see how to enable caching.
Modern alternatives to next/image
By default, Next.js optimizes images and serves them directly from the Next.js web server. That is the default behavior of the built-in image optimization API. However, for some reason, you may want to delegate image optimization to other cloud providers like Cloudinary, Cloudflare, Contentful, and Fastly. Most of the cloud providers are not exactly alternatives to the next/image
component because you can still use them with the next/image
component.
However, Next.js won’t be responsible for the image optimization. You’re delegating the image optimization to the cloud provider. To opt out of the Next.js automatic image optimization, you need to create a custom loader. A loader is a function that takes the image src
, width
, and quality
as parameters and returns the image URL string.
You can create a custom loader for each instance of the next/image
component or declare a custom loader in the next.config.js
file. The code below illustrates how you can create a custom loader for a particular instance of the next/image
component. It declares a custom loader for the Cloudinary Image API and sets it as the value of the next/image
component’s loader
prop:
import Image from "next/image";
//https://res.cloudinary.com/demo/image/upload/w_300,c_limit,q_auto/turtles.jpg
function cloudinaryLoader({ src, width, quality }) {
const params = ["f_auto", "c_limit", `w_${width}`, `q_${quality || "auto"}`];
return `https://res.cloudinary.com/demo/image/upload/${params.join(
","
)}${src}`;
}
export default function TurtleImage() {
return (
<Image
src="/turtles.jpg"
loader={cloudinaryLoader}
width={300}
height={300}
alt="Turtle"
priority={true}
/>
);
}
Alternatively, you can also use the loaderFile
property of your next.config.js
file to configure a custom loader for all instances of your next/image
component like so:
module.exports = {
images: {
loader: 'custom',
loaderFile: './custom-loader.js',
},
}
The value of the loaderFile
property is the path to your custom loader. This path should be relative to the root directory of your application.
export default function customImageLoader({ src, width, quality }) {
return `https://example.com/${src}?w=${width}&q=${quality || 75}`;
}
You can check these examples in the Next.js docs to learn how to create custom loaders for the common cloud providers. Some cloud providers also provide their own image components that you can use instead of the next/image
component.
As an example, ImageKit has the Next.js ImageKit SDK for rendering images optimized by ImageKit. You need to read the documentation for the corresponding cloud provider to know whether it has a custom image component you can use in a Next.js project.
Conclusion
Image optimization in Next.js improves the user and developer experience with a native, game-changing, and powerful API that’s easy to work with and extend. This inadvertently solves a major Core Web Vitals need and helps websites achieve a higher SEO rank, all starting and ending with next/image
.
LogRocket: Full visibility into production Next.js apps
Debugging Next applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your Next.js app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.
The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.
Modernize how you debug your Next.js apps — start monitoring for free.