62

I am using NextJS Image component. I want the image to fill 100% width and take as much height as it needs to maintain the aspect ratio. I have tried many different variations of this code but it will not work unless I define a fixed height on the parent div.

export default function PhotoCard({ img }: Props) {
      return (
        <div className="relative w-full h-32 my-2">
          <Image alt={img.title} src={img.url} layout="fill" objectFit="cover" />
        </div>
      );
    }

This is the current behaviour images in app

2
  • Try to set the image directly inside the <Image /> tag. Commented Sep 18, 2021 at 2:56
  • 5
    did you find any fix for this? Commented Jun 26, 2022 at 21:10

11 Answers 11

127

From Next.js 13, the next/image component allows styling the underlying image directly using style/className. This means you can apply width: 100% and height: auto on the Image component directly.

import Image from 'next/image';

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

Or, if using Tailwind CSS.

import Image from 'next/image';

<Image
    src={img1}
    width="0"
    height="0"
    sizes="100vw"
    className="w-full h-auto"
/>

Before Next.js 13, the above feature is only available through next/future/image, and from version 12.2, next/future/image was still experimental and can be enabled in next.config.js under the experimental flag.

module.exports = {
    experimental: {
        images: {
            allowFutureImage: true
        }
    },
    // Other configs
}
Sign up to request clarification or add additional context in comments.

1 Comment

This doesn't work, you have to duplicate code, because height and width are used for resizing params passed to the server. Passing 0 gives bad values.
20

For those who are getting the error like:

 Image with src "image path" has either width or height modified, but not the other. If you use CSS to change the size of your image, also include the styles 'width: "auto"' or 'height: "auto"' to maintain the aspect ratio.

Setting width and height attribute to 0 and adding style with your desired height or width and setting either of width or height to auto will fix the issue

             <Image
                src="image path"
                height={0}
                width={0}
                style={{width:'120px', height: "auto" }}
              />

2 Comments

This helped remove the error. Thank you for that. However, after applying height and width to 0, and applying Tailwind classes: className="w-[300px] h-auto", the image is blurred. Any idea why that could be the case?..
Had the same issue too after trying this solution; but fixed it by adding style={{ height: 142, width: 122 }}. Below is my example: jsx <Image src="image path" alt="image" height={142} width={122} style={{ height: 142, width: 122 }} />
6

As Next.js has mentioned in their documentation, width and height properties are required in order to avoid layout shift, using layout="fill" will only fill the container height and width that is previously set. This basically means that in order to maintain the aspect ratio, you have to know the image height and width in advance.

Luckily though, Next.js also provided us a work around with this problem with an event called onLoadingComplete, which gives us an event parameter that contains both image natural height and width.

<Image
   layout="fill"
   src="/cat.jpg"
   onLoadingComplete={e => console.log(e)} // {naturalHeight: ..., naturalWidth: ...}
/>

There are plenty of options that you can do to maintain image aspect ratio with this information, like useState to set the height and the width of the element or make the image responsive, depends on your need. In any case, hope this was helpful.

3 Comments

This should be higher up! Setting only one dimension for images and auto-ing the other is a pretty common design in normal images, I wonder why NextJS can't support that feature more easily.
@Mo. The future image component looks promising tbh.
5

I found my own solution, I just write the same width and height as it was when I saw that warning, and added style with auto to width and height :

            <Image
              alt="logo"
              src="/logo.png"
              width={110}
              height={65}
              style={{ width: "auto", height: "auto" }}
            />

Comments

3

2023 Solution

If you load image from external url just remove width and height and use fill

<Image
      loading={"lazy"}
      fill
      src={post.image}
/>

1 Comment

Unfortunately this will work only if the image url has exactly the desired dimensions to display.
3

Update: In current Next.js v14, width and height accepts only number | undefined type,

<Image
  src={img}
  alt={imgName}
  className="md:w-24 w-20 h-auto" // Using tailwindcss
  width={0}
  height={0}
/>

Use className, if you are using tailwindcss / other css modules otherwise use style property.

Comments

1

if you're using tailwind, this worked for me:

import Image from "next/image";
<Image
      src={someImg}
      width="75" //set a width or height
      alt="img"
      className="h-auto" // add h-auto (if you've set width)
    />

Comments

0

I have found a solution without using next/future/image and with using css with width-[100%] on the parent div like so.

           <div
              className="mx-auto w-[100%] md:bg-card md:w-[720px] max-w-4/5"
              key={img.imageProps.src}
            >
              <Image
                placeholder="blur"
                {...img.imageProps}
                layout={'responsive'}
                alt={`${chapterData.chapterNumber} image`}
              />
            </div>

{...img.imageProps} is a object that looks like this that has original height and width.

export type ImageProps = {
  blurDataURL: string;
  src: string;
  height: number;
  width: number;
  type?: string | undefined;
};

You can get these image props using something like plaiceholder, it comes loaded with blurImage data url.

const convertImages = async (image: string) => {
    const { base64, img } = await getPlaiceholder(image, { size: 14 });
    return {
      imageProps: {
        ...img,
        blurDataURL: base64,
      },
    };
  };

OR

You can create your own function to get the height and width for each image individually before displaying it, which is required by the next <Image/> Hope this helps.

Comments

0

I don't think setting the height and width to 0 would be a good idea, I used the answer commented by @Lawrence Macharia and set the width and height property of style object same as what I passed to Nextjs Image component:

<Image src={imageSrc} width={400} height={600} alt={t.title}  style={{ height: 600, width: 400 }}/>

Comments

-1

SIMPLE

  1. Look at the file, the width and height, mainly in svg file property and force the size, adjusting the object-fit and if necessary the aspect-ratio logic. SVG's dimension props

  2. Look at father component display's logic, mainly if you use flex. Pay attention to the computed dimension at elements inspetion of DevTools and force width and height to that. Computed dimension at devtools

2 Comments

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
-2

You can try to set width and height with "%" way..

<Image src={image.url} alt={image.title} width="100%" height="100%" layout="responsive" objectFit="contain"/>

or you can set the width with the "vw" property like this..

<Image src={image.url} alt={image.title} width="100vw" height="100%" layout="responsive" objectFit="contain"/>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.