画像は、ウェブ上で最も重く最も多いリソースです。そのため、画像を最適化すると、ウェブサイトのパフォーマンスが大幅に向上します。多くの場合、画像を最適化すると、送信されるバイト数が少なくなってネットワーク時間が短縮されます。また、ユーザーのデバイスに適したサイズの画像を配信することで、ユーザーに送信されるバイト数を最適化することもできます。
ページに画像を追加するには、<img>
要素または <picture>
要素、または CSS の background-image
プロパティを使用します。
イメージサイズ
画像リソースを使用する際の最初の最適化は、画像を適切なサイズで表示することです。この場合、サイズという用語は画像のディメンションを指します。他の変数を考慮しなければ、500 x 500 ピクセルのコンテナに表示される画像は 500 x 500 ピクセルに最適なサイズになります。たとえば、1, 000 ピクセルの正方形の画像を使用すると、画像の大きさは必要に応じて 2 倍になります。
しかし、適切な画像サイズの選択には多くの変数が関わるため、どのケースでも適切な画像サイズを選択するタスクは非常に複雑になります。2010 年に iPhone 4 がリリースされたとき、画面解像度(640x960)は iPhone 3(320x480)の 2 倍でした。ただし、iPhone 4 の画面の物理サイズは iPhone 3 とほぼ同じです。
すべて高解像度で表示すると、テキストと画像が大幅に縮小されます(正確には以前の半分のサイズ)。1 ピクセルが 2 つのデバイス ピクセルになりました。これをデバイス ピクセル比(DPR)と呼びます。iPhone 4 と、それ以降にリリースされた多くの iPhone モデルでは、DPR は 2 でした。
前述の例で、デバイスの DPR が 2 で、画像が 500 x 500 ピクセルのコンテナに表示される場合、1,000 ピクセルの正方形の画像(組み込みサイズと呼ばれます)が最適なサイズになります。同様に、デバイスの DPR が 3 の場合は、1,500 ピクセルの正方形の画像が最適なサイズになります。
srcset
<img>
要素は srcset
属性をサポートしており、ブラウザが使用できる画像ソースのリストを指定できます。指定する各画像ソースには、画像 URL と、幅またはピクセル密度記述子を含める必要があります。
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>
上記の HTML スニペットでは、ピクセル密度記述子を使用して、DPR が 1 のデバイスでは image-500.png
、DPR が 2 のデバイスでは image-1000.jpg
、DPR が 3 のデバイスでは image-1500.jpg
を使用するようにブラウザに指示します。
まったく無駄に見えるかもしれませんが、特定のページに最適な画像を選択する際の考慮事項は画面の DPR だけではありません。ページのレイアウトも重要な要素です。
sizes
上記の解決策は、すべてのビューポートで同じ CSS ピクセルサイズで画像を表示する場合にのみ有効です。多くの場合、ページのレイアウトとそれに伴うコンテナのサイズは、ユーザーのデバイスによって異なります。
sizes
属性を使用すると、ソースサイズのセットを指定できます。各ソースサイズは、メディア条件と値で構成されます。sizes
属性は、画像の想定表示サイズを CSS ピクセルで記述します。srcset
幅記述子と組み合わせると、ブラウザはユーザーのデバイスに最適な画像ソースを選択できます。
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
srcset="/image-500.jpg 500w, /image-1000.jpg 1000w, /image-1500.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
上記の HTML スニペットでは、srcset
属性に、ブラウザが選択できる画像候補のリストをカンマで区切って指定しています。リスト内の各候補は、画像の URL と、画像の本来の幅を示す構文で構成されます。画像の固有のサイズは画像のディメンションです。たとえば、1000w
という記述子は、画像の固有の幅が 1, 000 ピクセルであることを示します。
この情報を使用して、ブラウザは sizes
属性のメディア条件を評価します。この例では、デバイスのビューポートの幅が 768 ピクセルを超えると、画像が 500 ピクセルの幅で表示されるよう指示されます。小さいデバイスでは、画像は 100vw
(ビューポートの幅全体)で表示されます。
ブラウザはこの情報を srcset
画像ソースのリストと組み合わせて、最適な画像を見つけることができます。たとえば、ユーザーが画面幅 320 ピクセル、DPR 3 のモバイル デバイスを使用している場合、画像は 320 CSS pixels x 3 DPR = 960 device pixels
に表示されます。この例では、最も近いサイズの画像は image-1000.jpg
で、固有の幅は 1, 000 ピクセル(1000w
)です。
ファイル形式
ブラウザでは、さまざまな画像ファイル形式がサポートされています。WebP や AVIF などの最新の画像形式は、PNG や JPEG よりも圧縮率が高く、画像ファイルのサイズが小さくなるため、ダウンロードにかかる時間が短縮されます。最新の形式で画像を提供することで、リソースの読み込み時間が短縮され、Largest Contentful Paint(LCP)が低下する可能性があります。
WebP は、すべての最新ブラウザで動作する幅広くサポートされている形式です。WebP は、JPEG、PNG、GIF よりも圧縮率に優れており、非可逆圧縮と可逆圧縮の両方が可能です。WebP は、JPEG コーデックにはない機能である非可逆圧縮を使用している場合でも、アルファ チャンネル透明度をサポートしています。
AVIF は新しい画像形式で、WebP ほど広くサポートされているわけではありませんが、どのブラウザでも相応にサポートされています。AVIF は非可逆圧縮と可逆圧縮の両方をサポートしており、JPEG と比較して 50% を超えるコスト削減がテストで示されているケースもあります。AVIF は、広色域(WCG)機能とハイ ダイナミック レンジ(HDR)機能も提供しています。
圧縮
画像に関しては、次の 2 種類の圧縮があります。
非可逆圧縮では、量子化によって画像の精度が低下しますが、彩度サブサンプリングを使用して追加の色情報が破棄されることがあります。非可逆圧縮は、ノイズや色の多い高密度画像(一般的には類似した内容の写真や画像)で特に効果的です。これは、非可逆圧縮によって生成されるアーティファクトが、そのような詳細な画像では気づく可能性が非常に低いためです。ただし、線画、同じように鮮明なディテール、テキストなど、鮮明なエッジを含む画像では、非可逆圧縮の効果が低下する可能性があります。非可逆圧縮は、JPEG、WebP、AVIF の画像に適用できます。
可逆圧縮では、データを失うことなく画像を圧縮できるため、ファイルサイズが小さくなります。可逆圧縮では、隣接するピクセルとの差分に基づいてピクセルが記述されます。GIF、PNG、WebP、AVIF の画像形式では可逆圧縮が使用されます。
画像は、Squoosh、ImageOptim、または画像最適化サービスを使用して圧縮できます。圧縮の際、すべてのケースに適した汎用的な設定はありません。画質とファイルサイズの適切なバランスが見つかるまで、さまざまな圧縮レベルを試すことをおすすめします。一部の高度な画像最適化サービスでは、この処理を自動的に行うことができますが、すべてのユーザーにとって経済的に実現できるとは限りません。
<picture>
要素
<picture>
要素を使用すると、複数の画像候補を柔軟に指定できます。
<picture>
<source type="image/avif" srcset="image.avif">
<source type="image/webp" srcset="image.webp">
<img
alt="An image"
width="500"
height="500"
src="/image.jpg"
>
</picture>
<picture>
要素内で <source>
要素を使用すると、AVIF 画像と WebP 画像のサポートを追加できますが、ブラウザが最新の形式をサポートしていない場合は、より互換性のある以前の画像形式にフォールバックできます。この方法では、ブラウザは最初に指定された <source>
要素のうち、一致するものを選択します。この形式で画像をレンダリングできる場合は、その画像が使用されます。それ以外の場合、ブラウザは次に指定された <source>
要素に進みます。上記の HTML スニペットでは、AVIF 形式が WebP 形式よりも優先されます。AVIF 形式も WebP 形式もサポートされていない場合は、JPEG 形式にフォールバックします。
<picture>
要素内に <img>
要素をネストする必要があります。alt
、width
、height
の各属性は <img>
で定義され、どの<source>
が選択されたかにかかわらず使用されます。
<source>
要素は media
属性、srcset
属性、sizes
属性もサポートしています。前述の <img>
の例と同様に、さまざまなビューポートでどの画像を選択するかをブラウザに指示します。
<picture>
<source
media="(min-resolution: 1.5x)"
srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
>
</picture>
media
属性は、メディア条件を受け取ります。上記の例では、デバイスの DPR がメディア条件として使用されます。DPR が 1.5 以上のデバイスは、最初の <source>
要素を使用します。<source>
要素は、ビューポートが 768 ピクセルを超えるデバイスでは、選択された画像候補が幅 500 ピクセルで表示されることをブラウザに指示します。小さいデバイスではビューポートの幅全体になります。media
属性と srcset
属性を組み合わせると、使用する画像を細かく制御できます。
これを次の表に示します。この表では、いくつかのビューポートの幅とデバイスのピクセル比が評価されます。
ビューポートの幅(ピクセル) | 1 DPR | 1.5 DPR | 2 DPR | 3 DPR |
---|---|---|---|---|
320 | 500.jpg | 500.jpg | 500.jpg | 1000.jpg |
480 | 500.jpg | 500.jpg | 1000.jpg | 1500.jpg |
560 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1024 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1920 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
DPR が 1 のデバイスでは、image-500.jpg
イメージがダウンロードされます。これには、ほとんどのデスクトップ ユーザー(500 ピクセル幅の外部サイズ)でイメージがダウンロードされます。一方、DPR が 3 のモバイル ユーザーは、サイズが大きくなる可能性のある image-1500.jpg
(DPR が 3 のデスクトップ デバイスで使用されているものと同じ画像)をダウンロードします。
<picture>
<source
media="(min-width: 560px) and (min-resolution: 1.5x)"
srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
<source
media="(max-width: 560px) and (min-resolution: 1.5x)"
srcset="/image-1000-sm.jpg 1000w, /image-1500-sm.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
>
</picture>
この例では、<picture>
要素を調整して <source>
要素を追加し、DPR の高い幅の広いデバイスで異なる画像を使用するようにしています。
ビューポートの幅(ピクセル) | 1 DPR | 1.5 DPR | 2 DPR | 3 DPR |
---|---|---|---|---|
320 | 500.jpg | 500.jpg | 500.jpg | 1000-sm.jpg |
480 | 500.jpg | 500.jpg | 1000-sm.jpg | 1500-sm.jpg |
560 | 500.jpg | 1000-sm.jpg | 1000-sm.jpg | 1500-sm.jpg |
1024 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1920 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
この追加のクエリを使用すると、image-1000-sm.jpg
と image-1500-sm.jpg
が小さいビューポートに表示されていることを確認できます。デスクトップ デバイスの画質を損なうことなく、そのサイズと密度では圧縮アーティファクトが顕著に現れないため、この追加情報により画像をさらに圧縮できます。
または、srcset
属性と media
属性を調整して、小さなビューポートで大きな画像が表示されないようにすることもできます。
<picture>
<source
media="(min-width: 560px)"
srcset="/image-500.jpg, /image-1000.jpg 2x, /image-1500.jpg 3x"
>
<source
media="(max-width: 560px)"
srcset="/image-500.jpg 1x, /image-1000.jpg 2x"
>
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
>
</picture>
上記の HTML スニペットでは、デバイス ピクセル比の記述子を優先して幅の記述子が削除されています。モバイル デバイスに配信される画像は、DPR が 3 のデバイスであっても /image-500.jpg
または /image-1000.jpg
に制限されます。
複雑さを管理する方法
レスポンシブ画像を扱う場合、画像ごとにさまざまなサイズ バリエーションや形式があります。上記の例では、各サイズのバリエーションが使用されていますが、AVIF と WebP は除外されています。バリアントの数はいくつにする必要がありますか?多くのエンジニアリングの問題と同様に、答えは「場合により」である傾向があります。
最適なサイズになるようにバリエーションを増やしたくなるかもしれませんが、画像バリエーションを追加するごとにコストがかかり、ブラウザ キャッシュの使用効率が低下します。バリアントが 1 つしかないため、すべてのユーザーに同じ画像が届くため、効率的にキャッシュできます。
一方、多数のバリエーションがある場合は、各バリアントが別のキャッシュ エントリを必要とします。バリアントのキャッシュ エントリが期限切れになり、送信元サーバーからイメージを再度取得する必要がある場合、サーバーのコストが上昇し、パフォーマンスが低下する可能性があります。
それとは別に、HTML ドキュメントのサイズはバリエーションごとに大きくなります。各画像に数キロバイトの HTML を送信している場合があります。
Accept
リクエスト ヘッダーに基づいて画像を提供する
Accept
HTTP リクエスト ヘッダーは、ユーザーのブラウザでどのコンテンツ タイプが認識されるかをサーバーに通知します。サーバーはこの情報を使用して、HTML レスポンスに余分なバイトを加えずに、最適な画像形式を提供できます。
if (request.headers.accept) {
if (request.headers.accept.includes('image/avif')) {
return reply.from('image.avif');
} else if (request.headers.accept.includes('image/webp')) {
return reply.from('image.webp');
}
}
return reply.from('image.jpg');
上記の HTML スニペットは簡易版のコードです。このコードをサーバーの JavaScript バックエンドに追加して、最適な画像形式を選択して配信することができます。リクエストの Accept
ヘッダーに image/avif
が含まれている場合、AVIF 画像が配信されます。Accept
ヘッダーに image/webp
が含まれている場合は、WebP 画像が配信されます。上記のいずれの条件も満たさない場合は、JPEG 画像が配信されます。
ほぼすべての種類のウェブサーバーの Accept
リクエスト ヘッダーの内容に基づいてレスポンスを変更できます。たとえば、mod_rewrite
を使用して、Accept
ヘッダーに基づいて Apache サーバーで画像リクエストを書き換えることができます。
これは、画像コンテンツ配信ネットワーク(CDN)で行われる動作とは異なります。Image CDN は、画像を最適化し、ユーザーのデバイスとブラウザに応じて最適な形式で送信するための優れたソリューションです。
重要なのは、バランスを取り、妥当な数の画像候補を生成すること、ユーザー エクスペリエンスへの影響を測定することです。画像によって得られる結果は異なります。また、各画像に適用される最適化は、ページ内の画像のサイズとユーザーが使用しているデバイスによって異なります。たとえば、全幅のヒーロー画像には、e コマースの商品リスティング ページのサムネイル画像よりも多くのバリエーションが必要になる場合があります。
遅延読み込み
loading
属性を使用すると、ビューポートに表示されるときに画像を遅延読み込みするようにブラウザに指示できます。属性値 lazy
は、画像がビューポートに入る(またはその近く)になるまで画像をダウンロードしないようブラウザに指示します。これにより帯域幅が節約され、ブラウザがすでにビューポートにある重要なコンテンツをレンダリングするために必要なリソースを優先できるようになります。
decoding
decoding
属性は、画像のデコード方法をブラウザに指示します。値 async
は、画像を非同期でデコードできることをブラウザに伝えます。これにより、他のコンテンツのレンダリング時間が短縮される可能性があります。値 sync
は、画像を他のコンテンツと同時に表示するようブラウザに指示します。デフォルト値の auto
では、ブラウザがユーザーに最適な方法を決定できます。
画像デモ
知識を試す
どの画像形式が可逆圧縮をサポートしているか?
非可逆圧縮に対応している画像形式を教えてください。
幅記述子(1000w
など)は、srcset
属性で指定された画像候補についてどのような内容をブラウザに伝えますか。
sizes
属性は、適用された <img>
要素についてブラウザに伝えるものですか?
<img>
要素の srcset
で指定された候補を表すロジックを読み込む必要があります。<img>
要素の srcset
属性から読み込まれる画像の固有の幅。
次のトピック: 動画のパフォーマンス
画像は、ウェブで最も一般的なメディアタイプですが、パフォーマンスに関して注意が必要なメディアタイプではありません。動画はウェブ全体で使用されるもう 1 つの一般的なタイプのメディアであり、独自のパフォーマンスに関する考慮事項が存在します。このコースの次のモジュールでは、動画を最適化する方法と、動画を効率的に読み込む方法について学習します。