Next.js provides a built-in Image component, which provides benefits like lazy loading, and improved performance. You get all these benefits for free just from using the Image component to display your images, but one issue with the component is its slightly convoluted approach to styling.
Next.js has a lot of other benefits over React, and you can check out some more of them in this article.
In this article, I’ll explain what works, and what you might need to work around when styling your component.
Image Component
Next.js allows you to pass styles directly to the component through props. You can use either the style prop or the classNames prop. This works with most styling, but you may run into issues with sizing. Next.js provides its own method for how your image will size itself, which can override your styling.
If you have a simple image with a fixed width and height in pixels, you can use the fixed layout option, and simply provide the width and height as props. For more advanced options, however, you may have to pick a different layout option.
To demonstrate this, I’ve created a simple component to display a profile. Here’s what our component looks like:
And here’s our code, which uses some simple styling from TailwindCSS:
export default function Images() {
return (
<div className="flex h-screen items-center justify-center bg-neutral-900">
<div className="m-auto w-72 overflow-clip rounded bg-neutral-900 text-white shadow">
<div className="relative flex aspect-square w-full flex-col items-center justify-center">
<Image
src={backgroundImg}
layout="fill"
className="absolute brightness-50"
/>
<div className="aspect-square w-1/2 overflow-clip rounded-full">
<div className="aspect-square w-1/2 overflow-clip rounded-full">
<Image src={profileImg} />
</div>
</div>
<div className="z-10 flex flex-col items-center justify-center">
<div className="font-bold">Omari Thompson-Edwards</div>
<div>React Developer</div>
</div>
</div>
</div>
</div>
);
}
Our first Image component is used to create the background. Luckily with this usage, we can work with the Next.js styling. We can use the fill layout to make the image fill the full component, and then apply some styling through TailwindCSS to darken our background slightly.
If we take a look at the second usage, the circular profile picture:
<div className="aspect-square w-1/2 overflow-clip rounded-full">
<Image src={profileImg} />
</div>
Here, our aim is to have the profile picture circular and take up half the width of the container. The issue with styling Next.js’ Image component, in this case, is that there is no layout option for the sizing we want.
We can work around this using a wrapper component with the size we want. The Image component can then fill up the full size of the container, which is the size we want.
NB: The only style that needs to be applied to the wrapper is the sizing; since the image is the only thing in the wrapper, the remaining styling can be applied to either the wrapper or the image.
The layout prop comes with a few different configurations, and you can check out the full details on that here. To sum it up, the options are:
- “intrinsic” is the default option, the image will have a max size of its actual size, and will scale its width down to fit the container
- “fill” causes the image to fill the space of its container
- “fixed” can be combined with setting a “width” and “height” prop to give the image a fixed size in pixels
- “responsive” will cause the image to scale to fit the width of its container
Future Image
The next version of Next.js revamps the image component to simplify the API, removing the layout props in favour of just using class names, or whatever styling system you choose.
You can try out the new version by changing your import from ‘next/image’ to ‘next/future/image’.
You’ll also need to enable this in your Next.js config, by adding this:
experimental: {
images: {
allowFutureImage: true,
}
}
And you’ll also need to restart your development server for the change to take effect.
With that enabled, we can refactor our component to take advantage of the new functionality. The layout prop is completely gone, replaced by native CSS styling.
Here’s our new component:
export default function Images() {
return (
<div className="flex h-screen items-center justify-center bg-neutral-900">
<div className="m-auto w-72 overflow-clip rounded bg-neutral-900 text-white shadow">
<div className="relative flex aspect-square w-full flex-col items-center justify-center">
<Image
src={backgroundImg}
className="absolute h-full w-full brightness-50"
/>
<Image
className="z-10 aspect-square w-1/2 overflow-clip rounded-full"
src={profileImg}
/>
<div className="z-10 flex flex-col items-center justify-center">
<div className="font-bold">Omari Thompson-Edwards</div>
<div>React Developer</div>
</div>
</div>
</div>
</div>
);
}
We can remove the layout prop from our background, and instead use Tailwind to tell it to fill the space of the component.
Then we can also get rid of our wrapper component, and move the classes to the image component itself.
In a future version of Next.js, this will get moved to “next/image”, and the original image component will be moved to “next/legacy/image”, but for now you have to use this approach to use it.
Conclusion
Hopefully, that was a useful introduction to the quirks of styling images in Next.js. Let me know if you found this article interesting, if you’re having any troubles, or if you simply liked the article!
💬 Leave a comment