next/imageでサイズがわからない画像を使用する & 正しく表示されない場合の対処法


生成した画像をpositionを使用しレイアウトする必要があった時、位置やサイズが意図しない形で生成されて困ったので共有しておきます。

サイズがわからない画像で使用する編

概要

next/imageは基本的にwidthheightを渡す必要がありますが、APIからサイズやアスペクト比がバラバラな画像を受け取り表示する場合など、事前にサイズを指定したくないケースがあります。

実際のコード

const imageUrl = await getImage();

return <NextImage src={imageUrl} width={'指定したくない'} height={'指定したくない'} />

解決策

next/imageは widthheight または layout='fill' を渡す必要がある。
今回はサイズを指定したくないのでlayout='fill'objectFit='contain'を渡してあげるとうまくいく

const imageUrl = await getImage();

return <NextImage src={imageUrl} layout='fill' objectFit='contain' />

参考

https://nextjs.org/docs/api-reference/next/image#layout

外部から画像を持ってくる編

外部APIを叩いて画像を取得する場合はドメインを設定する必要がある。

ドメインの設定方法

domainsに追加していく
※microcmsの場合

next.config.js
const nextConfig = {
  ...
  images: {
    domains: ['images.microcms-assets.io'],
  },
};

module.exports = nextConfig;

参考

https://nextjs.org/docs/api-reference/next/image#domains

正しく表示されない場合の対処法編

概要

next/imageで生成した画像をpositionを使用しMasonryレイアウトを実装した時に位置やサイズが意図しない形で生成された

return <NextImage src={`${post.photo.url}?w=500`} layout="fill" objectFit="contain" />

解決策

hoge.tsx
return (
<div className={styles.imageContainer}>
  <NextImage src={url} layout="fill" objectFit="contain" />
</div>
)
style.module.scss
.imageContainer: {
  /* next12からは div → span */
  & > div: {
    position: static !important;
  }
  img: {
    position: static !important;
    width: 100% !important;
    height: auto !important;
  }
}

解説

next/imageで生成される要素はdiv>imgです(next12はdivタグがspanになる)

<div style="...">
  <img style="..." src="" />
</div>

<div><img>position:absolute;付与されており、positionを使ったレイアウトだと崩れてしまいます。なので上書きします。

参考

https://github.com/vercel/next.js/discussions/18739