Image
component to optimize imagesThe Next Image
Component is the built-in image optimization solution for Next.js. It extends the native HTML <img>
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.
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 <img>
element:
<img src="https://blog.logrocket.com/image.jpg">
You can add an alternative text (alt
) to describe the image for screen readers or if the browser fails to load it:
<img src="https://blog.logrocket.com/image.jpg%20alt="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
.
Image
componentFrameworks 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.
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.
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.
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.
Images are lazy loaded by default and can be served in modern formats like WebP in supported web browsers.
Next.js can also automatically adopt future image formats and serve them to browsers that support those formats.
Image
ComponentThe 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 <img>
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.
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="https://blog.logrocket.com/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:
module.exports = { images: { deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], }, }
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 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="https://blog.logrocket.com/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)
.
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:
<Image src="https://blog.logrocket.com/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.
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, will improve the load time of your web page or app:
<Image src="https://blog.logrocket.com/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.
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} />;
By default, Next.js dynamically optimizes images on request and caches them in the <distDir>/cache/images
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.
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="https://blog.logrocket.com/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.
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
.
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.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage environment variables in Next.js, which influence how an application behaves in different contexts and environments.
useActionState
in React: A practical guide with examplesDiscover how React’s useActionState Hook makes it easier to handle user actions, especially form submissions and async state changes.
Compare two libraries that support creating 3D experiences in the browser. Learn how to get started with each, their core features, and key differences.
Discover how to integrate frontend AI tools for faster, more efficient development without sacrificing quality.
One Reply to "How to use the Next.js <code>Image</code> component to optimize images"
Anyone has problems with the quality prop? While my app running in dev mode all my served images are small in size. After the app got builded the pictures are served in original sizes. It seems that the quality prop doesn’t has a effect on it.