Next.js Image Component
Images play a crucial role in web applications, but they can significantly impact performance if not handled properly. Next.js provides a built-in Image
component that optimizes images automatically, making your applications faster and providing a better user experience.
Introduction to the Image Component
The Image
component in Next.js extends the HTML <img>
element with features like:
- Automatic image optimization
- Lazy loading (images load as they enter the viewport)
- Preventing layout shift during image loading
- Responsive images based on device size
- Modern image formats like WebP when supported by browsers
Getting Started with the Image Component
Basic Usage
First, import the Image
component from next/image
:
import Image from 'next/image';
function MyComponent() {
return (
<Image
src="/images/profile.jpg"
alt="Profile picture"
width={500}
height={300}
priority
/>
);
}
In this example:
src
: The path to your image (local or remote)alt
: Accessibility attribute describing the imagewidth
andheight
: Dimensions of the imagepriority
: Boolean that loads the image immediately (important for above-the-fold images)
Output
When rendered, Next.js will:
- Generate multiple sizes of your image for different devices
- Serve the image in modern formats like WebP if the browser supports it
- Only load the image when it enters the viewport (unless
priority
is set) - Prevent layout shift by reserving the space based on width and height
Local vs Remote Images
Local Images
When using local images stored in your project, Next.js can optimize them at build time:
import Image from 'next/image';
import profilePic from '../public/images/profile.jpg';
function Profile() {
return (
<Image
src={profilePic}
alt="Profile picture"
// width and height are automatically provided
placeholder="blur" // Optional blur-up while loading
/>
);
}
Remote Images
For external images, you need to:
- Specify the
width
andheight
- Add the domain to your Next.js configuration
// In your component
import Image from 'next/image';
function Avatar() {
return (
<Image
src="https://example.com/profile.jpg"
alt="Avatar"
width={64}
height={64}
/>
);
}
// In next.config.js
module.exports = {
images: {
domains: ['example.com'],
},
}
Responsive Images
Using fill
Property
When you want the image to fill its parent container:
import Image from 'next/image';
function Banner() {
return (
<div style={{ position: 'relative', height: '300px' }}>
<Image
src="/images/banner.jpg"
alt="Website banner"
fill
style={{ objectFit: 'cover' }}
/>
</div>
);
}
Note: The parent element must have position: relative
when using fill
.
Using sizes
for Responsive Behavior
import Image from 'next/image';
function ResponsiveImage() {
return (
<Image
src="/images/hero.jpg"
alt="Hero image"
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
style={{ objectFit: 'contain' }}
/>
);
}
This tells browsers what size the image will be at different breakpoints, helping them select the right image source.
Advanced Features
Image Placeholders
You can show a blur placeholder while the image loads:
import Image from 'next/image';
import profilePic from '../public/profile.jpg';
function Profile() {
return (
<Image
src={profilePic}
alt="Profile"
placeholder="blur"
// blurDataURL is automatically generated for local images
/>
);
}
For remote images, you can provide a base64-encoded image as placeholder:
import Image from 'next/image';
function RemoteImageWithBlur() {
return (
<Image
src="https://example.com/photo.jpg"
alt="Remote photo"
width={700}
height={475}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCAAIAAoDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAhEAACAQMDBQAAAAAAAAAAAAABAgMABAUGIWEREiMxUf/EABUBAQEAAAAAAAAAAAAAAAAAAAMF/8QAGhEAAgIDAAAAAAAAAAAAAAAAAAECEgMRkf/aAAwDAQACEQMRAD8AltJagyeH0AthI5xdrLcNM91BF5pX2HaH9bcfaSXWGaRmknyJckliyjqTzSlT54b6bk+h0R//2Q=="
/>
);
}
Loading Priority
For important images (like hero images), use the priority
attribute:
import Image from 'next/image';
function HeroSection() {
return (
<Image
src="/images/hero.jpg"
alt="Hero image"
width={1200}
height={600}
priority
/>
);
}
This tells Next.js to load the image immediately, without waiting for it to enter the viewport.
Real-World Example: Image Gallery
Let's create a responsive image gallery with the Next.js Image component:
import Image from 'next/image';
import styles from './Gallery.module.css';
const images = [
{ src: '/gallery/image1.jpg', alt: 'Beach sunset', width: 1200, height: 800 },
{ src: '/gallery/image2.jpg', alt: 'Mountain view', width: 800, height: 1200 },
{ src: '/gallery/image3.jpg', alt: 'City skyline', width: 1200, height: 800 },
// More images...
];
function Gallery() {
return (
<div className={styles.gallery}>
{images.map((image, index) => (
<div key={index} className={styles.galleryItem}>
<Image
src={image.src}
alt={image.alt}
width={image.width}
height={image.height}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
className={styles.galleryImage}
/>
</div>
))}
</div>
);
}
export default Gallery;
With CSS like:
/* Gallery.module.css */
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 16px;
padding: 16px;
}
.galleryItem {
position: relative;
height: 300px;
overflow: hidden;
border-radius: 8px;
}
.galleryImage {
object-fit: cover;
transition: transform 0.3s ease;
}
.galleryImage:hover {
transform: scale(1.05);
}
Best Practices
- Always specify
alt
text for accessibility - Use
width
andheight
attributes to prevent layout shifts - Add
priority
to important above-the-fold images - Use the
sizes
attribute for responsive images - Use
fill
withobjectFit
when images need to fill their container - Add domains to
next.config.js
when using remote images - Consider using
placeholder="blur"
for better loading experience
Common Issues and Solutions
Issue: "Error: Invalid src prop"
Make sure you've added the domain to your Next.js config:
// next.config.js
module.exports = {
images: {
domains: ['example.com', 'cdn.yoursite.com'],
},
}
Issue: Layout shifts
Ensure you always provide:
width
andheight
for standard images- Proper container styling with
position: relative
when usingfill
// Good practice
<Image src="/image.jpg" alt="Description" width={800} height={600} />
// For fill mode
<div style={{ position: 'relative', height: '300px' }}>
<Image src="/banner.jpg" alt="Banner" fill style={{ objectFit: 'cover' }} />
</div>
Summary
The Next.js Image component is a powerful tool that helps you:
- Automatically optimize images for better performance
- Prevent layout shifts with proper image loading
- Serve responsive images appropriate for each device
- Improve loading experience with lazy loading and placeholders
By using this component instead of the standard HTML <img>
tag, you ensure your Next.js application delivers images in the most efficient way possible, improving both performance and user experience.
Additional Resources
Exercises
- Create a responsive hero section with an optimized background image
- Build an image carousel that uses the Image component with proper loading priorities
- Convert an existing project using standard
<img>
tags to use Next.js Image components - Create a photo gallery with blur-up placeholders for a better loading experience
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)