使用固定宽度和自动高度的NextJS图像组件

33

我正在使用NextJS的图像组件。我希望该图像能够以100%的宽度填充,并且需要尽可能地保持其纵横比来占据所需的高度。我已经尝试了许多不同的代码变体,但除非在父

上定义一个固定的高度,否则它将无法正常工作。

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>
      );
    }

这是当前的行为 应用程序中的图像


尝试直接在<Image />标签内设置图像。 - hisam
5
你找到解决这个问题的方法了吗? - wick3d
6个回答

82

从 Next.js 13 开始,next/image 组件允许直接使用 style/className 样式来对底层图像进行样式设置。这意味着您可以直接在 Image 组件上应用 width: 100%height: auto

import Image from 'next/image';

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

或者,如果使用Tailwind CSS。

import Image from 'next/image';

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

在 Next.js 13 之前,上述功能只能通过 next/future/image 实现。从版本 12.2 开始,next/future/image 仍处于实验阶段,并可以在 next.config.js 中启用 experimental 标志。

module.exports = {
    experimental: {
        images: {
            allowFutureImage: true
        }
    },
    // Other configs
}

5

正如Next.js在他们的文档中提到的那样,为了避免布局偏移,需要使用宽度和高度属性,使用layout="fill"仅填充先前设置的容器高度和宽度。这基本上意味着为了保持纵横比,您必须事先知道图像的高度和宽度。

幸运的是,Next.js还为我们提供了一个解决此问题的方法,使用名为onLoadingComplete的事件,该事件提供了一个包含图像自然高度和宽度的事件参数。

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

有很多方法可以使用这些信息来保持图像的纵横比,例如使用useState设置元素的高度和宽度,或者使图像具有响应性,具体取决于您的需求。无论如何,希望这些内容能够有所帮助。


1
这应该放得更高!在普通图像中,仅设置一个维度并自动调整另一个维度是一种常见的设计方式,我想知道为什么NextJS不能更轻松地支持这个功能。 - sayandcode
layout已被弃用 https://nextjs.org/docs/api-reference/next/legacy/image - Mo.
2
@Mo。未来的图像组件看起来很有前途,说实话。 - raven2218

1

2023解决方案

如果您从外部url加载image,只需删除widthheight,并使用fill

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

0

我已经找到了一个解决方案,不使用next/future/image而是使用css在父div上使用width-[100%]

           <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} 是一个对象,它看起来像这样,具有原始的高度和宽度。

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

你可以使用像 plaiceholder 这样的工具来获取这些图像属性,它还会加载带有 blurImage 数据 URL。

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

或者

您可以创建自己的函数,以在显示每个图像之前获取其高度宽度,这是下一个 <Image/> 所需要的。 希望这对您有所帮助。


0
对于那些遇到以下错误的人:
 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.

将宽度和高度属性设置为0,并添加具有所需高度或宽度的样式,并将宽度或高度之一设置为自动,即可解决此问题。
             <Image
                src="image path"
                height={0}
                width={0}
                style={{width:'120px', height: "auto" }}
              />

-1

你可以尝试使用“%”的方式设置宽度和高度。

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

或者您可以使用“vw”属性来设置宽度,就像这样...

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接