# Next.jsのImageが使いにくいという人へ
Next.jsのImageが使いにくいという人へ
2022/12/25:更新
暫定のシンプルな実装方法
いずれにせよheightは設定しないといけないことになります.これはCore Web VitalsのCLSを損ねるからでしょうね.
記事内にあるlayout='fill'
はv13.0からはfillをtrueにすることで指定できます.この方法を取るしか無いでしょう.また記事内で扱わなかったaspect-ratioを使用することで,短く書くことも可能です.
また,objectFit='contain'
も非推奨になったので,自分で追加すると良いでしょう.
以下例(TailwindCSSで失礼)
import type { FC } from 'react';
import NextImage from 'next/image';
export const Image: FC<Props> = () => {
return (
<div className="relative aspect-square">
<NextImage
className="object-contain"
src={url}
alt={alt || ''}
fill
/>
</div>
);
};
今回の変更は一見何も使いやすくなってないかと思いますが,Core Web Vitals的には正しいと思います.
よくわからない人は,HTMLのimg要素にwitdhとheightが必須になったものくらいに思っておけばいいかと思います.ちょっとだるい感じですが,それだけすればいい感じにしてくれるのです.
参考
New
Legacy
Next.jsにはHTMLのimg
タグよりNext.jsが用意したImage Componentを使用することが推奨されています.
Image Componentが何かわからない人は一度公式をご覧ください.
私も詳しいことわからないのですが,Vercelなどの対応しているHostingサービスでデプロイするときにこのComponentを使っていると画像ファイルがいい感じになるようなので,できれば使っていきたいところです.
今回はそんなImage Componentが使いやすくなるための知識を浅く簡潔に記録しておきます.
この記事は2022/03/18頃に書かれたものであり,その後のアップデート次第で仕様が変わることもあるのでご注意ください.
ちなみに,結構前のアップデートでこのImage Componentは大分使いやすくなりました.私の最初のイメージはwidthとheightを指定しないと使えない使いづらいやつだったのですが,どうやら工夫すればそんなことしなくても良さそうです!
基本的な使い方
一般的にはHTMLのimg
タグと同じようにsrc
やalt
属性などを指定して使います.
import Image from 'next/image';
const MyComponent = () => {
return (
<div>
{/* 通常のimgタグ */}
<img src='/logo.png' alt='logo' />
{/* Next.jsのImage Component */}
<Image src='/logo.png' alt='logo' />
</div>
);
};
これだけ見ると簡単に思えるのですが,様々な条件が整っていないとNext.jsさんは劣化の如く怒り,実エラーのオンパレードになります.
ハマりやすい2つのポイント
srcのURLについて
まずはsrcの指定方法です.大きく2つあると思ってください.
publicフォルダから参照(型:string)
<Image src='/logo.png' layout='fill' alt='logo' />
いつもの書き方なのですが,publicフォルダ配下しか参照できないというのと,**layout
属性をfill
としない場合にwidthとheightの指定を求められる**点だけ注意が必要です.
/hogehoge
と書くことでpublic/hogehoge
を表します.
そして,layout
属性をfill
とすると「え...」っとなります.(後で詳しく)
publicフォルダ以外からimportして参照(型:StaticImageData)
import Image from 'next/image';
import imageSrc from '../assets/logo.png'; // 相対パスや絶対パスは好みで
const MyComponent = () => {
return (
<div>
<Image src={imageSrc} alt='logo' />
</div>
);
};
imageSrc
という名前で画像ファイルを読み込み,Image Componentのsrc
へ渡しています.
この場合,サイズは元の画像のサイズが表示されます.(調整方法は後で詳しく)
この方法では画像ファイルがどこにあろうが表示することができます.
スタイルの調整について
ここまでで画像を表示することができるものの思い通りにスタイル(CSSを当てる)ことができないという人のために自分がよく使っている簡単なテクニックを紹介します.
layout='fill'
とする
<Image src={imageSrc} layout='fill' alt='logo' />
とすることで,目の前が画像に覆われることがあるでしょう.
これはposition: absolute;
とwidth: 100%;
があたったようなものと思っていいでしょう.
なので,position: relative;
を持つ親を探し続けてそこまで広がるわけです.
これを解決したい場合は
<div style={{ position: 'relative', width: '100px', height: '100px' }}>
<Image src={imageSrc} layout='fill' alt='logo' />
</div>
のように親にwidthとheightが確保されている状態である必要があります.
またこれでは,画像のアスペクト比(画像の縦横比)を維持することが難しいため,objectFitを併用することをおすすめします.
例:
<div style={{ position: 'relative', width: '100px', height: '100px' }}>
<Image src={imageSrc} layout='fill' objectFit='contain' alt='logo' />
</div>
objectFit='contain'
とすれば,アスペクト比を保ったまま横いっぱいor縦いっぱいに広がり,余白が出るものの,画像全体が見えるようにしてくれます.
objectFit='cover'
とすれば,アスペクト比を保ったまま横いっぱいor縦いっぱいに広がり,画像全体が見えなくてもいいので,余白がないようにしてくれます.
文章だと少し分かりづらいですが,これはCSS Propertyのobject-fitと同じ挙動です.
わからない人は,新しくなったMDNで確認してみるといいでしょう.
layout='responsive'
とする
<Image src={imageSrc} layout='responsive' alt='logo' />
こちらはこのImage Componentの親のサイズに応じていい感じになってくれますので,比較的使いやすいです.
<div style={{ width: '100px' }}>
<Image src={imageSrc} layout='responsive' alt='logo' />
</div>
とすれば,親の100pxに合わせて画像が横に広がり,高さはアスペクト比を保ったまま広がります.
画像にwidth: 100%;
があたっている状態という感じですね.
というわけでケースバイケースではあるのですが,基本的で簡単なテクニックを紹介しました.
Discussion