レスポンシブな画像を配信する

Katie Hempenius 氏
Katie Hempenius

PC サイズの画像をモバイル デバイスに配信すると、必要以上のデータ使用量が 2 ~ 4 倍になる可能性があります。画像に対して「万能」のアプローチではなく、デバイスごとに異なる画像サイズを提供します。

レスポンシブ画像と Core Web Vitals

レスポンシブ画像を配信する場合は、ユーザーのデバイスの表示機能を評価し、それらの条件に基づいて表示に最適な画像候補のセットのいずれかを選択します。前述のように、メリットのないデバイスに過剰な画像データを配信するのではなく、デバイスに適したサイズの画像を提供します。スマートフォンやタブレットなどの小型デバイスでは、ノートパソコンなどの画面の大きなデバイスと比較してデータ使用量が削減されます。

画像の読み込みが高速になるという効果は、ページの Largest Contentful Paint(LCP)にも及びます。たとえば、ページの LCP 要素が画像の場合、その LCP 候補のリソース読み込み時間が短縮されます。

リソースの読み込み時間が短いほど、LCP 画像の読み込み時間は短くなり、ページの LCP スコアが向上します。LCP が低いと、サイトの読み込みが速くなったと、ユーザーが認識できるようになります。特に、ページの読み込み中にビューポートに表示されるコンテンツのうち、一番大きなものになります。レスポンシブ画像を配信すると、ページ上の他のリソースとの帯域幅の競合も減るため、ページの読み込み速度全般を改善できます。

画像のサイズを変更

最も一般的な画像サイズ変更ツールは、sharp npm パッケージImageMagick CLI ツールの 2 つです。

sharp パッケージは、画像のサイズ変更を自動化する場合(たとえば、ウェブサイト上のすべての動画で複数サイズのサムネイルを生成する場合など)に適しています。ビルド スクリプトやツールとすばやく簡単に統合できます。一方、ImageMagick は完全にコマンドラインから使用されるため、1 回限りの画像サイズ変更には便利です。

鋭い

sharp を Node スクリプトとして使用するには、このコードを個別のスクリプトとしてプロジェクトに保存し、それを実行してイメージを変換します。

const sharp = require('sharp');
const fs = require('fs');
const directory = './images';

fs.readdirSync(directory).forEach(file => {
  sharp(`${directory}/${file}`)
    .resize(200, 100) // width, height
    .toFile(`${directory}/${file}-small.jpg`);
  });

ImageMagick

画像を元のサイズの 33% にサイズ変更するには、ターミナルで次のコマンドを実行します。

convert -resize 33% flower.jpg flower-small.jpg

次のコマンドを実行して、画像のサイズを変更して幅 300 ピクセル、高さ 200 ピクセルの範囲内に収めます。

# macOS/Linux
convert flower.jpg -resize 300x200 flower-small.jpg

# Windows
magick convert flower.jpg -resize 300x200 flower-small.jpg

いくつのイメージ バージョンを作成する必要がありますか。

この質問に対する唯一の「正しい」答えはありません。ただし、1 つの画像のサイズを 3 ~ 5 種類提供するのが一般的です。配信する画像サイズが多いほどパフォーマンスは向上しますが、サーバーで占有される容量も増え、記述する HTML の数も少々増えます。

その他のオプション

Thumbor(オープンソース)や Cloudinary などの画像サービスもぜひチェックしてください。画像サービスは、オンデマンドでレスポンシブ画像(および画像操作)を提供します。Thumbor を設定するには、サーバーにインストールします。Cloudinary がこれらの細かい処理を行います。サーバーの設定は必要ありません。どちらもレスポンシブ画像を簡単に作成できます。

複数のイメージ バージョンを提供する

複数のイメージ バージョンを指定すると、ブラウザにより最適なものが選択されます。

変更前 変更後
<img src="flower-large.jpg"> <img src="flower-large.jpg" srcset="flower-small.jpg 480w, flower-large.jpg 1080w" size="50vw">

この最終結果を得るため、<img> タグの src 属性、srcset 属性、sizes 属性はすべて相互作用します。

「src」属性

src 属性を使用すると、srcset 属性と sizes 属性をサポートしないブラウザでもこのコードが機能します。ブラウザでこれらの属性がサポートされていない場合は、src 属性で指定されたリソースの読み込みにフォールバックします。

「srcset」属性

srcset 属性は、画像ファイル名とその幅または密度記述子のカンマ区切りのリストです。

この例では、幅記述子を使用しています。480w は、flower-small.jpg の幅が 480 ピクセルであることをブラウザに通知します。1080w は、flower-large.jpg の幅が 1,080 ピクセルであることをブラウザに通知します。

「幅記述子」は一見するとおしゃれに聞こえますが、単にブラウザに対して画像の幅を伝える手段です。これにより、ブラウザはサイズを決定するために画像をダウンロードする必要がなくなります。

追加の実習: さまざまな画像サイズを提供するための密度記述子に関する知識は必要ありません。 密度記述子の仕組みについては、解像度の切り替えに関する Codelab をご覧ください。 密度記述子は、デバイスのピクセル密度に応じて異なる画像を表示するために使用されます。

「sizes」属性

サイズ属性は、画像が表示されるときの画像の幅をブラウザに伝えます。ただし、sizes 属性は表示サイズに影響しません。そのためには CSS が必要です。

ブラウザは、この情報と、ユーザーのデバイスについて把握している情報(寸法やピクセル密度)を使用して、読み込む画像を決定します。

ブラウザが「sizes」属性を認識できない場合は、代わりに「src」属性で指定された画像を読み込みます。(ブラウザでは「sizes」属性と「srcset」属性のサポートが同時にリリースされているため、ブラウザは両方の属性をサポートするか、どちらもサポートしないかのどちらかになります)。

追加の実習: サイズ属性を使用して複数のスロットサイズを指定することで、さらに魅力的なものにすることもできます。これにより、ビューポートのサイズごとに異なるレイアウトを使用するウェブサイトに対応できます。その方法については、こちらの複数スロットのコードサンプルをご覧ください。

(その他の)追加演習

前述のすべてのクレジット(画像は複雑です)に加えて、同じコンセプトをアート ディレクションにも使用できます。アート ディレクションとは、(同じ画像の異なるバージョンではなく)見た目がまったく異なる画像を異なるビューポートに提供することです。詳しくは、アート ディレクションの Codelab をご覧ください。

確認

レスポンシブ画像を実装したら、Lighthouse を使用して、画像を見逃さないようにできます。Lighthouse のパフォーマンス監査([Lighthouse] > [Options] > [Performance])を実行し、[Properly size images] の監査結果を確認します。結果に、サイズ変更が必要な画像が一覧表示されます。