DEV Community

Cover image for Responsive fix for the Next.js Image component
Felix Häberle
Felix Häberle

Posted on

Responsive fix for the Next.js Image component

Currently, layout="responsive" requires you to set width and height which you don't want to set because you don't know what the aspect ratio is going to be.

This is a new change since version 10.0.1 where the team around Next deprecated the unsized prop, replacing it with layout="fill" – which doesn't gives you the same functionality.

Also, if you're going to set layout="fill" and objectFit="cover" on the Image component you will get a strange behavior. There are cases in which you can fix this with position: relative on the parent item, but then you also have to set width and height which you don't want in case of a responsive image.

There is an easy fix to this problem, you only have to set a wrapper around the Image component to give a bit of extra styling.

First, we have to add the wrapping item with the class image-container. Please adjust this to fit your styling needs, e.g. if you're using styled-components the syntax will look slightly different.

<div className={'image-container'}>
  <Image src={path} layout="fill" className={'image'} />
</div>
Enter fullscreen mode Exit fullscreen mode

For this to work, it's important that you add two classes: image-container to the parent element and image to the Image component. After adding these classes, you should add this styling.

.image-container {

  width: 100%;

  > div {
    position: unset !important;
  }

  .image {
    object-fit: contain;
    width: 100% !important;
    position: relative !important;
    height: unset !important;
  }
}
Enter fullscreen mode Exit fullscreen mode

And that's it! 🎉

Your images should now display with the right dimensions and should scale up to 100% width and at the same time having the correct height.

Latest comments (14)

Collapse
 
orkhangg profile image
Orkhan Aliyev • Edited

layout="fill" is deprecated. use fill={true} instead as follows:
<div className={'image-container'}>
<Image src="IMAGE_SOURCE" className="image" fill={true} alt="ALT_TEXT"/>
</div>

Collapse
 
shriekdj profile image
Shrikant Dhayje

thanks dude

Collapse
 
hamishjohnson profile image
Hamish

This destroys the cumulative layout shift features of Next/Image priority tag

Collapse
 
pablowbk profile image
Pablo

Thanks! been struggling with refactoring a component that was using "responsive", this hgave me the perfect grounds to find a solution. cheers!

Collapse
 
sameersmr profile image
SAMEER MATHAN

thanks man

Collapse
 
hveveris profile image
Haris

Thanks, very useful! XD

Collapse
 
fkrautwald profile image
Frederik Krautwald

That was very helpful. I was struggling to hide and show images responsively. Now, I got a couple of great image components to use.

Collapse
 
studywithdesign profile image
studywithdesign

I have used layout = "responsive" with width = {500} height = {270}

Collapse
 
paymanbaseri profile image
Payman Baseri

stackoverflow.com/a/68838835/7757900

with a little changes

Collapse
 
jonm01 profile image
Jon Mathew

With the above fix backdrop-filter: blur(5px); stopped working on a div that overlays on the image. Issue is only with Chrome and Firefox but on Safari it works

Collapse
 
joshuatuscan profile image
Joshua Tuscan

This saved me from a layout hell. Thanks so much!

Collapse
 
yonmoyonmo profile image
Yeo, Wonmo

thank you man

Collapse
 
ivan_jrmc profile image
Ivan Jeremic • Edited

Any reason you use curly braces in className? It is just a string so you can use just a string without curly braces. Good article this helped me fixing a problem I had!

Collapse
 
markwilliams profile image
Mark Williams

I'm guessing it's so it's easier to refactor to using string interpolation.