🖼️

[Next.js] next/image で画像の遅延読み込み中に、サムネイルをぼかさずに表示する方法

に公開

アルダグラムでソフトウェアエンジニアとして活動している松田です。

Next.jsでは、next/image (または Next.js 12 以前の next/legacy/image) コンポーネントを使用して効率的に画像を表示できます。
このコンポーネントは標準の <img> タグを拡張し、遅延読み込みや画像最適化といった機能を提供します。

機能の一つに、メイン画像が読み込まれるまでの間、代替画像(サムネイル)をぼかして表示するプレースホルダーがあります。
しかし、ユースケースによっては、このぼかし効果を適用したくない場合もあるでしょう。
本稿では、next/image および next/legacy/image コンポーネントで、画像の遅延読み込み中にサムネイルをぼかさずに表示する方法を解説します。

手法

早速、実現手法について、簡潔に述べます。

next/image での実装例

  • サムネイル画像の Data URL を用意
  • priority 属性を false に設定し、遅延読み込みを有効化
  • placeholder 属性にサムネイル画像の Data URL を指定
import Image from 'next/image'
import { FC } from 'react'
import styles from 'path/to/your/styles.module.css'

const SandboxComponent: FC = () => {
  // ...

  return (
    <Image
      src="/path/to/original-image.jpg" // オリジナル画像のパス
      priority={false} // 遅延読み込みを有効にする
      placeholder="data:image/png;base64,******..." // サムネイル画像のdata URL
      className={styles.nextImage}
      {...otherProps}
    />
  )
}

next/legacy/image での実装例

next/image でも利用可能ですが、こちらの実装ではスタイルを上書きしているので、前述の実装手法をお勧めします。

  • サムネイル画像の Data URL を用意
  • priority 属性を false に設定し、遅延読み込みを有効化
  • placeholder 属性を blur に設定し、blurDataURL 属性にサムネイル画像のパスを指定
  • CSSで filter: none !important を指定し、ぼかしを無効化
import Image from 'next/image'
import { FC } from 'react'
import styles from 'path/to/your/styles.module.css'

const SandboxComponent: FC = () => {
  // ...

  return (
    <Image
      src="/path/to/original-image.jpg" // オリジナル画像のパス
      priority={false} // 遅延読み込みを有効にする
      placeholder="blur" // プレースホホルダー設定 (blur or empty)
      blurDataURL="/path/to-thumbnail-image.jpg" // サムネイル画像のパス
      className={styles.nextImage}
      {...otherProps}
    />
  )
}
/* styles.module.css */
/**
 * img タグを明示的に指定することで、
 * next/image, next/legacy/image
 * どちらのコンポーネントでも適用される
 */
.nextImage img {
  filter: none !important; /* ぼかしを無効化 */
  /* ... */
}

解説

next/image コンポーネントの関連仕様と上記実装例について、もう少し詳しく解説します。

next/imagenext/legacy/image

Next.js 13 で next/image コンポーネントは大幅に刷新されました。従来の next/image (Next.js 12 以前) は next/legacy/image として引き続き利用可能です。

バージョンアップ時などに next/image 関連で予期せぬ表示崩れや不具合が発生した場合は、一時的に next/legacy/image に切り替えて対応するのも一つの手です。

https://nextjs.org/docs/pages/api-reference/components/image
https://nextjs.org/docs/pages/api-reference/components/image-legacy

priority 属性

画像の読み込み優先度を指定する真偽値の属性です。

A boolean that indicates if the image should be preloaded.

defaultで false ですので、明示的な指定は必須ではありません。
ただ、これが true の場合、画像は優先的にpreloadされ、その場合、遅延読み込みが無効化されます。
したがって、今回のようなユースケースでは明示的に false にしておくのが無難です。

placeholder 属性

メイン画像の読み込み中に表示されるプレースホルダーの種類を指定します。

  • empty: 何も表示しない(画像読み込み完了まで空白)
  • blur: blurDataURL と併用し、ぼかした画像をプレースホルダーとして使用
  • data:image/... (Next.js 13.4.14以降の next/image でサポート): 指定された Data URL を直接プレースホルダーとして使用

留意点として、 next/legacy/image では、 data:image/... の直接指定がサポートされていません。

v13.4.14 placeholder prop support for data:/image…

したがって、Data URLを利用する場合は、 blur 指定の上で blurDataURL 属性にて指定する必要があります。

blurDataURL 属性

placeholder="blur" が指定された場合に、プレースホルダーとして使用される画像の Data URL を指定します。
この属性に指定した画像は、コンポーネント内部で filter: blur(...) スタイルが自動適用され、ぼかして表示されます。
next/legacy/image の実装例で示したのは、この自動適用されるスタイルを CSS で filter: none !important によって上書きしてぼかしを無効化する、という手法になります。

まとめ

本稿では、next/image および next/legacy/image コンポーネントを使用して、画像の遅延読み込み中にサムネイル(プレースホルダー画像)をぼかさずに表示する方法を解説しました。

  • next/image (v13以降): placeholder に直接 Data URL を指定するのが最も簡単です。
  • next/legacy/image: placeholder="blur"blurDataURL を使い、CSS でぼかしを無効化します。

画像の読み込み戦略は、UX向上において重要です。
表示するコンテンツやデザインの要件に応じて最適な手法を選択できるよう、引き出しは多いに越したことはありません。

また、日進月歩のフロントエンド技術の情報を取り扱う際は、情報の信頼性はもとより、情報の鮮度や対象バージョンにも気を配る必要があります。
Next.js のバージョンアップの過渡期にこのような実装に取り組んだことで、改めてその重要性を実感しました。


もっとアルダグラムのエンジニア組織を知りたい人は、ぜひ下記の情報もチェックしてみてください!

アルダグラム Tech Blog

Discussion