Introduction
Images play a crucial role in web development, but they can also significantly impact a website's performance. To address this issue, Next.js provides the Image component, which offers automatic image optimization and various features for optimizing image loading and rendering. In this tutorial, we will explore a checklist for optimizing images in Next.js and provide code examples for each optimization step.
1. Local Images are imported
To use a local image, import your .jpg
, .png
, or .webp
image files. Next.js will automatically determine the width and height of your image based on the imported file. These values are used to prevent Cumulative Layout Shift while your image is loading.
import Image from 'next/image'
import profilePic from '../public/me.png'
export default function Page() {
return (
<Image
src={profilePic}
alt="Picture of the author"
/>
)
}
2. Remote Images have width and height
When using a remote image, you need to provide the width and height attributes manually. These attributes are used to infer the correct aspect ratio of the image and avoid layout shifts during image loading.
import Image from 'next/image'
export default function Page() {
return (
<Image
src="https://s3.amazonaws.com/my-bucket/profile.png"
alt="Picture of the author"
width={500}
height={500}
/>
)
}
3. Remote image URLs are in next.config
To safely allow image optimization for remote images, define a list of supported URL patterns in the next.config.js
file. Be as specific as possible to prevent malicious usage.
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 's3.amazonaws.com',
port: '',
pathname: '/my-bucket/**',
},
],
},
};
4. Largest Contentful Paint Images have priority
To improve the Largest Contentful Paint (LCP) performance, add the priority
property to the image that will be the LCP element for each page. This allows Next.js to prioritize the loading of the image, resulting in a meaningful boost in LCP.
import Image from 'next/image'
export default function Home() {
return (
<>
<h1>My Homepage</h1>
<Image
src="/me.png"
alt="Picture of the author"
width={500}
height={500}
priority
/>
<p>Welcome to my homepage!</p>
</>
)
}
5. Images are sized correctly
To prevent image-based layout shifts and ensure good performance, it's crucial to size your images correctly. The Next.js Image component provides three ways to size images using the next/image
component:
- Automatic sizing with a static import: When importing local images using a static import, Next.js automatically determines the width and height based on the imported file. This ensures that the browser reserves enough space for the image before it loads, preventing layout shifts.
import Image from 'next/image';
import profilePic from '../public/me.png';
export default function Page() {
return (
<Image
src={profilePic}
alt="Picture of the author"
/>
);
}
- Explicit sizing with
width
andheight
properties: For remote images or when you know the dimensions in advance, you can explicitly provide thewidth
andheight
attributes to thenext/image
component. This allows the browser to allocate the appropriate space for the image.
import Image from 'next/image';
export default function Page() {
return (
<Image
src="https://example.com/image.jpg"
alt="Description of the image"
width={600}
height={400}
/>
);
}
- Implicit sizing with the
fill
property: If you don't know the size of your images or want them to fill their parent container, you can use thefill
property. Thefill
property allows the image to expand and fill its parent element. Ensure that the parent element has a determined space on the page.
import Image from 'next/image';
export default function Page() {
return (
<div className="image-container">
<Image
src="/image.jpg"
alt="Description of the image"
layout="fill"
/>
</div>
);
}
6. Styling uses className or style
When it comes to styling the Next.js Image component, it's important to follow the recommended guidelines. Here's how you should approach styling:
Using className (recommended)
Use the className
prop for styling. It allows you to apply styles using CSS Modules, global stylesheets, or any other preferred styling method. This ensures better maintainability and separation of concerns. It also works perfectly with TailwindCSS.
import Image from 'next/image';
export default function Page() {
return (
<div className="image-container">
<Image
src="/image.jpg"
alt="Description of the image"
width={600}
height={400}
className="custom-image"
/>
</div>
);
}
Using style
Alternatively, you can use the style
prop to assign inline styles to the image. This is useful for applying specific styles that are not defined in external stylesheets.
import Image from 'next/image';
export default function Page() {
const imageStyles = {
borderRadius: '50%',
boxShadow: '0 0 10px rgba(0, 0, 0, 0.2)',
};
return (
<div>
<Image
src="/image.jpg"
alt="Description of the image"
width={200}
height={200}
style={imageStyles}
/>
</div>
);
}
Please note that using the styled-jsx
library is not recommended for styling the Next.js Image component. The styled-jsx
styles are scoped to the current component by default unless marked as global. Therefore, it's preferable to use the className
or style
prop for styling purposes.
7. Parent of images with fill have position relative and display block
If you're using the fill
property with the Next.js Image component, it's crucial to ensure that the parent element of the image has the correct CSS properties. This ensures that the image fills its parent container appropriately. Here's what you need to do:
Defining a class
- Set the parent element's
position
property torelative
. This establishes a positioning context for the image and allows it to fill the parent container correctly. - Set the parent element's
display
property toblock
. This ensures that the parent container takes up the entire width of its parent and allows the image to fill the available space.
.image-container {
position: relative;
display: block;
}
<div className="image-container">
<Image
src="/image.jpg"
alt="Description of the image"
width={600}
height={400}
fill
/>
</div>
Using TailwindCSS
- Apply the
relative
andblock
utility classes to the parent container. Therelative
class establishes a positioning context, while theblock
class ensures the parent container takes up the full width of its parent.
<div className="relative block">
<Image
src="/image.jpg"
alt="Description of the image"
width={600}
height={400}
fill
/>
</div>
Conclusion
Optimizing images is crucial for improving website performance and providing a smooth user experience. In this tutorial, we explored a checklist for optimizing images in Next.js By following these steps and utilizing the powerful features of the Next.js Image component, you can ensure that your website's images are optimized for performance. Happy coding! 🚀