120

I have a Next.js app, and I need an image that fills the full height of its container while automatically deciding its width based on its aspect ratio.

I have tried the following:

<Image
    src="/deco.svg"
    alt=""
    layout="fill"
/>

This snippet compiles successfully, but on the frontend, I see the following error:

Error: Image with src "/deco.svg" must use "width" and "height" properties or "unsized" property.

This confuses me because according to the docs, these properties are not required when using layout="fill".

Zsolt Meszaros
  • 21,961
  • 19
  • 54
  • 57
Jake
  • 2,090
  • 2
  • 11
  • 24

19 Answers19

151

This is what worked for me.

with next/image:

<div style={{width: '100%', height: '100%', position: 'relative'}}>
  <Image
    alt='Mountains'
    src='/mountains.jpg'
    layout='fill'
    objectFit='contain'
  />
</div>

and with next/future/image:

<Image
    fill
    alt='Mountains'
    src='/mountains.jpg'
    sizes='100vw'/>

next/future/image

francis
  • 3,852
  • 1
  • 28
  • 30
  • 21
    Yup, the parent of Image must have `relative` properties. – Asad S Sep 29 '21 at 15:04
  • 1
    you are setting the absolute values for height and width , but the question states in percentage – Hussam Khatib Nov 28 '21 at 10:43
  • 1
    I just would like to add something to this answer, In my case, where I needed the image to be aligned to the left, you can add the attribute objectPosition="left"; It is passed to css object-position: "left"; More info - https://developer.mozilla.org/en-US/docs/Web/CSS/object-position – Piltsen May 10 '22 at 15:40
  • 1
    This is the perfect solution. For those trying this on a card that also has text content, separate the container of the image from the text container and add the `position: relative` to the image container only so it doesn't overlap both the content. – Victor Eke Sep 07 '22 at 00:25
  • 1
    Check out [next/future/image](https://nextjs.org/blog/next-12-3#nextfutureimage-component-stable)'s `fill` layout mode that causes the image to fill the parent element. – francis Sep 15 '22 at 14:18
  • With the new next/image - `fill` causes the `object-fit: fill` style to be set. This needs to be overridden in ``. – pilotpin Aug 01 '23 at 11:10
71

In 2023, every above solution is deprecated,

use below

<Image
  src="url"
  width={0}
  height={0}
  sizes="100vw"
  style={{ width: '100%', height: 'auto' }} // optional
/>

Github: https://github.com/vercel/next.js/discussions/18474#discussioncomment-5501724

Nisharg Shah
  • 16,638
  • 10
  • 62
  • 73
33
<img src="/path/to/image.jpg" alt="" title="" />

In NextJS 12 and below

<Image src="/path/to/image.jpg" alt="" title="" width="100%" height="100%" layout="responsive" objectFit="contain"/>
Muhammet Can TONBUL
  • 3,217
  • 3
  • 25
  • 37
  • 17
    100% isn't a valid width - Error: Image with src has invalid "width" property. Expected a numeric value in pixels but received "100%". – Oly Dungey Nov 15 '22 at 07:08
  • Yes you are right. Overridden with NextJS 13. I hope to find a solution regarding this and update my answer. @OlyDungey – Muhammet Can TONBUL Nov 15 '22 at 09:39
23

Here is a way: For example I want to have an image that covers the whole width & height of its container which is a div.

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

And here is the style: (There is a container div that occupies half width & height of viewport & my image will cover it.)

// Nested Styling
.image-container {
    width: 50vw;
    height: 50vh;
    position: relative;

    .image {
        width: 100%;
        height: 100%;
        position: relative !important;
        object-fit: cover; // Optional
    }
}

// Or Normal Styling
.image-container {
    width: 50vw;
    height: 50vh;
    position: relative;
  }
.image-container .image {
    width: 100%;
    height: 100%;
    position: relative !important;
    object-fit: cover; // Optional
}
Peyman Baseri
  • 349
  • 1
  • 4
  • 7
11

I think also provide object-fit attribute on the Image element like this:-

<Image
    alt="Mountains"
    src="/mountains.jpg"
    layout="fill"
    objectFit="cover"
  />

Example provided by Nextjs can be https://github.com/vercel/next.js/blob/canary/examples/image-component/pages/layout-fill.js

Sonu Nigam
  • 279
  • 1
  • 7
10

And in next v13

       <Image
        src={src}
        width={200}
        height={160}
        alt={alt}
        sizes="(max-width: 768px) 100vw,
              (max-width: 1200px) 50vw,
              33vw"
        style={{ height: '100%', width: '100%' }} //The point is right there!
        //OR className='w-100 h-100'
      />

thanks to @Abílio Soares Coelho

Behzad
  • 1,740
  • 1
  • 22
  • 49
5

Maybe these other answers are for a different NextJS version, but none of them worked for me.

I am using NextJS v13.0.0

To accomplish this, I had the following JSX (using TailwindCSS, should be easy to translate to vanilla CSS):

<div className="h-screen relative">
  <Image
   src="/image.png"
   alt="pic of dog"
   fill={true}
  />
</div>

The important part here is making the parent div's position: relative (and setting it's height/width to be what you want for the image) and setting fill={true}. I got this from the NextJS Image documentation:

General image documentation: https://nextjs.org/docs/api-reference/next/image

Documentation on the fill attribute: https://nextjs.org/docs/api-reference/next/image#fill

Hope this helps someone!

deadbird11
  • 147
  • 2
  • 8
4
    <Image
    src="/deco.svg"
    alt="alternative text"
    fill
    style={{height: "100%", width:"100%"}}
    />
3
<Image
    src="/deco.svg"
    alt=""
    width={1000}
    height={1000}
    className='nextimg'
/>

in the place where your stylesheet add

.nextimg{
  width: 100%;
  height: auto;
}

BTW I added 1000 for width and height when its small amount image gets unclear. and think you can add your own styles for nextImg class

vimuth
  • 5,064
  • 33
  • 79
  • 116
2

For me in Next 13 worked fine after I imported the image and moved it away from public:

Before

<Image src='/link-to-public/img.png' alt="topmoto.pro" />

After

import img from "../assets/img.png";
...
<Image src={img} alt="topmoto.pro" />
Dima Dorogonov
  • 2,297
  • 1
  • 20
  • 23
1

In case you dont want to use absolute values for height and width , that is in px etc , you can do something like this

    <div style={{ position: "relative", width: "100%", paddingBottom: "20%" }} >
  <Image
    alt="Image Alt"
    src="/image.jpg"
    layout="fill"
    objectFit="contain" // Scale your image down to fit into the container
  />
</div>

Original source https://stackoverflow.com/a/66358533/12242764

Hussam Khatib
  • 600
  • 6
  • 17
1

If someone use NextJS with styled components. It works:

 const Container = styled.div`
  width: 100%;

  div, span {
    position: unset !important;
  }

  .image {
    object-fit: contain;
    width: 100% !important;
    position: relative !important;
    height: unset !important;
  }
`;

      <Container>
            <Image src={ src }
                   layout="fill"
                   className={ "image" }          
            />
        </Container>
benson23
  • 16,369
  • 9
  • 19
  • 38
BartD
  • 53
  • 5
1

On Next 13 when getting images from external URLs you can simply pass fill.

import Image from "next/image";

<Image
  src="https://unaqua.com.br/img/logo.png"
  fill
/>
Sam
  • 86
  • 1
  • 5
  • 2
    Using a relative parent element with a fixed width and height is required if you want to use `fill`, which is not useful if you don't have a fixed-size parent. \*This is quite useful if you want to have the image as a background.\* – sametcodes Mar 10 '23 at 03:21
  • this also works when using internal assets / images from /public folder – victor.ja May 30 '23 at 13:57
0

in Css Changes --->

.next-image {
    max-width: 100%;
    div {
        position: unset !important;
        padding: 0px !important;
        img {
            position: unset !important;
            width: 100% !important;
            height: 100% !important;
            max-height: 100% !important;
            max-width: 100% !important;
        }
    }
}

in JSX Or TSX Component --->>

<div className="next-image min-h-[150px]">
          <Image
            src={product?.images?.length ? product?.images[0]?.src : placeholderImage}
            width={imgWidth}
            height={imgHeight}
            layout="responsive"
            loading={imgLoading}
            quality={100}
            alt={product?.title || 'Product Image'}
            className="your Class"
          />
        </div>
0

When you use the layout property with a value of fill, Next.js will automatically set the position: absolute and top:0, left:0, right:0, and bottom:0 CSS properties on the Image component, which makes it fill its container. However, Next.js still needs to know the original dimensions of the image so that it can determine the aspect ratio and resize it accordingly.

You can either provide the width and height properties with the appropriate values, or you can use the unsized property instead, which tells Next.js to use the original dimensions of the image.

<Image  
  src="/deco.svg"
  alt = ""
  layout="fill"
  unsized
 />
Anurag Tripathi
  • 784
  • 1
  • 13
  • 13
-1
<img alt="" src="https://some/image/uri" loading="lazy" />

In NextJS

<div>
  <Image
    alt=""
    src="https://some/image/uri"
    width="100%"
    height="100%"
    layout="fill"
    objectFit="contain"
  />
</div>
Knight Rider
  • 972
  • 2
  • 10
  • 22
-1

works for me

<div
  style={{
    display: 'flex',
    flexDirection: 'column',
    height: 'auto',
    maxHeight: 343,
    position: 'relative'
  }}
>
  <Image
    src={`<YOU_IMAGE>`}
    alt="thumbnail"
    width="100%"
    height="100%"
    layout="responsive"
  />
</div>
Anecha Sun
  • 105
  • 1
  • 2
-1

Image with auto height and width. This will display actual size of image.

<Image
  src={selectedImage}
  width={0}
  height={0}
  alt=""
  style={{ width: "auto", height: "100%" }} // optional
/>

Image with fixed height and width.

<div style={{ position: "relative", width: "200px", height: "279px" }}>
  <Image
    src={selectedImage}
    fill
    alt=""
    style={{ objectFit: "cover" }}  // As per your requirement
  />
</div>
-3

It works for me in next.js image component

<Image src="/path/image.jpg" alt="" title="" width="100%" height="100%" layout="responsive" objectFit="cover"/>
Blastfurnace
  • 18,411
  • 56
  • 55
  • 70