Open In App

NextJS Image Component

Last Updated : 08 Aug, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

The image component in Next.js is powerful. It will assist you in optimizing and serving images efficiently. It has responsive loading and lazy loading built in, which can greatly boost the performance and user experience of your application by reducing the loading times of a page. This automatically changes the image size for the different screen resolutions and device sizes so it can serve up the needed variant of image which will ensure both performance and quality.

The image component provides extensive configurations where it is possible to set width, height, layout, and loader functions. Developers can, therefore, use such options easily to maintain images with a Next.js application without having to bother with optimizations.

These are the following topics that we are going to discuss:

Next.js Image Component

A Next.js specialized component that provides optimized images, which include so many features like lazy loading, responsive image sizes, and efficient caching.

Props

Prop

Example

src

src="/profile.png"

width

width={600}

height

height={800}

alt

alt="Photo of a person"

loader

loader={imageLoader}

fill

fill={true}

sizes

sizes="(max-width: 790px) 100vw, 44vw"

quality

quality={80}

priority

priority={true}

placeholder

placeholder="blur"

style

style={{objectFit: "contain"}}

onLoadingComplete

onLoadingComplete={img= done())}

onLoad

onLoad={event = done())}

onError

onError(event = fail()}

loading

loading= "lazy"

blurDataURL

blurDataURL="data:image/jpeg.."

overrideSrc

overrideSrc="/seo.png"

Required Props

  • src: The source of the image. This is a required prop and must be provided to render the image.
<Image src="/https/www.geeksforgeeks.org/path/to/image.jpg" />
  • width: The intrinsic width of the image in pixels.
<Image src="/https/www.geeksforgeeks.org/path/to/image.jpg" width={800} />
  • height: The intrinsic height of the image in pixels.
<Image src="/https/www.geeksforgeeks.org/path/to/image.jpg" width={800} height={600} />

Optional Props

Loader

A custom function to get image URLs.

import Image from 'next/image';
const imageLoader = ({ src, width, quality }) => {
return `https://example.com/${src}?w=${width}&q=${quality || 75}`;
};
export default function Page() {
return (
<Image
loader={imageLoader}
src="me.png"
alt="Picture of the author"
width={500}
height={500}
/>
);
}

Fill

Makes the image fill the parent element. The parent must have position: "relative", position: "fixed", or position: "absolute".

import Image from 'next/image';
export default function Page() {
return (
<div style={{ position: "relative", width: "100%", height: "100%" }}>
<Image
fill
src="/https/www.geeksforgeeks.org/example.png"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
</div>
);
}

Sizes

A string to define how wide the image will be at different screen sizes. This helps with performance by loading the right image size.

import Image from 'next/image';
export default function Page() {
return (
<div className="grid-element">
<Image
fill
src="/https/www.geeksforgeeks.org/example.png"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
</div>
);
}

Quality

Sets the quality of the image from 1 to 100. Default is 75.

<Image
src="/https/www.geeksforgeeks.org/example.png"
quality={75}
/>

Priority

Loads the image faster and disables lazy loading. Use for important images seen immediately when the page loads. Default is false.

<Image
src="/https/www.geeksforgeeks.org/example.png"
priority={true}
/>

Placeholder

A placeholder while the image loads. Options: empty, blur, data:image/.... Default is empty.

<Image
src="/https/www.geeksforgeeks.org/example.png"
placeholder="blur"
blurDataURL="data:image/png;base64,..."
/>

Advanced Props

Style

Pass CSS styles to the image.

const imageStyle = {
borderRadius: '50%',
border: '1px solid #fff',
};

export default function ProfileImage() {
return <Image src="..." style={imageStyle} />;
}

onLoad

Callback when the image is fully loaded.

<Image onLoad={(e) => console.log(e.target.naturalWidth)} />

onError

Callback if the image fails to load.

<Image onError={(e) => console.error(e.target.id)} />

Loading

Controls when the image loads. Options: lazy (default) or eager.

<Image src="/https/www.geeksforgeeks.org/example.png" loading="lazy" />

blurDataURL

Base64-encoded placeholder image before the main image loads. Used with placeholder="blur".

<Image
src="/https/www.geeksforgeeks.org/example.png"
placeholder="blur"
blurDataURL="data:image/png;base64,..."
/>

Unoptimized

Serves the image as-is without optimizing. Default is false.

<Image src="/https/www.geeksforgeeks.org/example.png" unoptimized />

overrideSrc

Overrides the automatically generated src attribute for the image.

<Image src="/https/www.geeksforgeeks.org/me.jpg" overrideSrc="/override.jpg" />

Other Props

Other properties passed to <Image /> are applied to the underlying <img> element, except for srcSet and decoding.

Configuration Options

remotePatterns

Protects your application by allowing only specific external images. Configure in next.config.js.

module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
port: '',
pathname: '/account123/**',
},
],
},
}

This ensures the src property of <Image /> starts with https://example.com/account123/. Any other URL will result in a 400 Bad Request.

Another Example:

module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: '**.example.com',
port: '',
},
],
},
}

This ensures the src property of <Image /> can start with any subdomain of example.com.

Domains

Deprecated since Next.js 14. Use remotePatterns instead.

Allows a list of allowed hostnames for external images.

module.exports = {
images: {
domains: ['assets.acme.com'],
},
}

This allows images from assets.acme.com.

loaderFile

Use a custom cloud provider to optimize images instead of Next.js's built-in optimization.

Configure in next.config.js:

module.exports = {
images: {
loader: 'custom',
loaderFile: './my/image/loader.js',
},
}

Example my/image/loader.js:

export default function myImageLoader({ src, width, quality }) {
return `https://example.com/${src}?w=${width}&q=${quality || 75}`;
}

Alternatively, you can use the loader prop for each <Image /> instance.

These configuration options help you manage how external images are handled in your Next.js application, ensuring security and flexibility.

Advanced Configuration

deviceSizes

Specify device width breakpoints to serve the correct image size for your users' devices.

module.exports = {
images: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
},
}

imageSizes

Specify image widths for images with the sizes prop. These widths should be smaller than the smallest size in deviceSizes.

module.exports = {
images: {
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
},
}

formats

Configure the image formats that the Image Optimization API will use, based on the browser's supported formats.

module.exports = {
images: {
formats: ['image/webp'],
},
}

Enable AVIF support:

module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
},
}

Note: AVIF compresses images smaller than WebP but takes longer to encode.

These advanced configurations allow you to fine-tune the image handling in your Next.js application, ensuring optimal performance and compatibility with different devices and browsers.

Caching Behaviour

The Image component leverages caching to optimize image delivery. Images are cached at the CDN level to ensure fast loading times and reduced server load.

The cache status of an image can be determined by reading the value of the x-nextjs-cache response header. The possible values are the following:

  • MISS: the path is not in the cache (occurs at most once, on the first visit)
  • STALE: the path is in the cache but exceeded the revalidate time so it will be updated in the background
  • HIT: the path is in the cache and has not exceeded the revalidate time

Animated Images

Animated images, such as GIFs, are supported by the Image component. It's important to ensure the correct handling of these images for optimal performance.

Example:

<Image src="/https/www.geeksforgeeks.org/path/to/animated.gif" width={800} height={600} />

Responsive Images

Static Import

For static images, you can import the image and create a responsive image using the sizes prop.

import Image from 'next/image'
import me from '../photos/me.jpg'

export default function Author() {
return (
<Image
src={me}
alt="Picture of the author"
sizes="100vw"
style={{
width: '100%',
height: 'auto',
}}
/>
)
}

Dynamic or Remote URL

For dynamic or remote images, provide the width and height props to maintain the aspect ratio.

import Image from 'next/image'
export default function Page({ photoUrl }) {
return (
<Image
src={photoUrl}
alt="Picture of the author"
sizes="100vw"
style={{
width: '100%',
height: 'auto',
}}
width={500}
height={300}
/>
)
}

Fill Prop

If the aspect ratio is unknown, use the fill prop and set position: relative on the parent element. Optionally, use objectFit for desired behavior.

import Image from 'next/image'
export default function Page({ photoUrl }) {
return (
<div style={{ position: 'relative', width: '300px', height: '500px' }}>
<Image
src={photoUrl}
alt="Picture of the author"
sizes="300px"
fill
style={{ objectFit: 'contain' }}
/>
</div>
)
}

Theme Detection CSS

To display different images for light and dark modes, use CSS media queries.

/* components/theme-image.module.css */
.imgDark {
display: none;
}
@media (prefers-color-scheme: dark) {
.imgLight {
display: none;
}
.imgDark {
display: unset;
}
}

Component:

import styles from './theme-image.module.css'
import Image from 'next/image'

export default function ThemeImage({ srcLight, srcDark, ...rest }) {
return (
<>
<Image {...rest} src={srcLight} className={styles.imgLight} />
<Image {...rest} src={srcDark} className={styles.imgDark} />
</>
)
}

Advanced Techniques

Picture Element

To show different images for light and dark modes using <picture>.

import { getImageProps } from 'next/image'
export default function Page() {
const common = { alt: 'Theme Example', width: 800, height: 400 }
const { props: { srcSet: dark } } = getImageProps({ ...common, src: '/dark.png' })
const { props: { srcSet: light, ...rest } } = getImageProps({ ...common, src: '/light.png' })

return (
<picture>
<source media="(prefers-color-scheme: dark)" srcSet={dark} />
<source media="(prefers-color-scheme: light)" srcSet={light} />
<img {...rest} />
</picture>
)
}

Art Direction

To show different images for mobile and desktop.

import { getImageProps } from 'next/image'
export default function Home() {
const common = { alt: 'Art Direction Example', sizes: '100vw' }
const { props: { srcSet: desktop } } = getImageProps({
...common,
width: 1440,
height: 875,
quality: 80,
src: '/desktop.jpg',
})
const { props: { srcSet: mobile, ...rest } } = getImageProps({
...common,
width: 750,
height: 1334,
quality: 70,
src: '/mobile.jpg',
})

return (
<picture>
<source media="(min-width: 1000px)" srcSet={desktop} />
<source media="(min-width: 500px)" srcSet={mobile} />
<img {...rest} style={{ width: '100%', height: 'auto' }} />
</picture>
)
}

Background Image Optimization

Convert the srcSet string to the image-set() CSS function for background images.

import { getImageProps } from 'next/image'
function getBackgroundImage(srcSet = '') {
const imageSet = srcSet
.split(', ')
.map((str) => {
const [url, dpi] = str.split(' ')
return `url("${url}") ${dpi}`
})
.join(', ')
return `image-set(${imageSet})`
}

export default function Home() {
const { props: { srcSet } } = getImageProps({ alt: '', width: 128, height: 128, src: '/img.png' })
const backgroundImage = getBackgroundImage(srcSet)
const style = { height: '100vh', width: '100vw', backgroundImage }

return (
<main style={style}>
<h1>Hello World</h1>
</main>
)
}

These methods will help you handle responsive images effectively in your Next.js application.


Next Article

Similar Reads