レスポンシブ画像

この Codelab は、Google Developers トレーニング チームが開発した「Developing Progressive Web Apps」トレーニング コースの一部です。Codelab を順番に扱うことで、このコースを最大限に活用できます。

コースの詳細については、プログレッシブ ウェブアプリ開発の概要をご覧ください。

はじめに

このラボでは、ウェブページ上の画像をすべてのデバイスで見栄えよくする方法を学びます。

学習内容

  • 複数のフォーム ファクタに適したサイズに画像をレスポンシブにする方法
  • srcsetsizes を使用してビューポートの幅に適した画像を表示する方法
  • picturesource をメディアクエリと組み合わせて使用し、ウィンドウのサイズを変更したときにページ上の画像が自動的に応答されるようにする方法

必要な予備知識

  • 簡易 HTML と CSS

必要なもの

  • テキスト エディタ
  • ターミナル/シェルにアクセスできるパソコン

GitHub から pwa-training-labs リポジトリをダウンロードまたは複製し、必要に応じて LTS バージョンの Node.js をインストールします。

優先ローカル開発用サーバーがない場合は、Node.js http-server パッケージをインストールします。

npm install http-server -g

responsive-images-lab/app/ ディレクトリに移動して、サーバーを起動します。

cd responsive-images-lab/app
http-server -p 8080 -a localhost -c 0

Ctrl-c を使用して、いつでもサーバーを終了できます。

ブラウザを開き、localhost:8080/ に移動します。

注: ラボの妨げにならないように、Service Worker の登録を解除し、localhost のすべての Service Worker キャッシュを削除します。Chrome DevTools で [Application] タブの [Clear storage] にある [Clear site data] をクリックして、この処理を行うことができます。

テキスト エディタでプロジェクトを開く場合は、responsive-images-lab/app/ フォルダを開きます。これにより、情報を簡単に整理できます。それ以外の場合は、パソコンのファイル システムでフォルダを開きます。app/ フォルダは、ラボを作成する場所です。

このフォルダには次のものが含まれます。

  • images フォルダにはサンプル画像が含まれていて、各画像には解像度の異なる複数のバージョンがあります
  • index.html は、サンプル サイト/アプリケーションのメインの HTML ページです。
  • styles/main.css は、サンプルサイトのカスケード スタイルシートです。

画像をレスポンシブにする前に、画像がはみ出ないようにしてください。

styles/main.css の TODO 2 を次のコードに置き換えます。

img {
  max-width: 100%;
}

コードを保存し、ブラウザでページを更新します。ウィンドウのサイズを変更してみてください。画像の幅はすべてウィンドウ内に収める必要があります。

説明

max-width の値は、含まれる要素(この場合は article 要素)の割合を表します。

注: vw の単位を使用して、ビューポートの幅の点で max-width を指定することもできます(例: 100vw)。この場合、画像とテキストの幅を合わせるためにパーセンテージ値を使用します。

目標は、画像の最終的な表示サイズよりも小さい最小サイズの画像をブラウザが取得できるようにすることです。srcset を使用すると、画像の取得時にブラウザが選択する解像度に応じて、画像のセットを一覧表示できます。ブラウザの選択は、ビューポートのサイズ、ビューポートに対する画像サイズ、ユーザーのデバイスのピクセル密度、ソースファイルのサイズによって異なります。

画像に srcset を追加する

index.html で TODO 3.1 を完成させるには、SFO 画像を含む img 要素に次の srcset 属性を追加します。

srcset="images/sfo-1600_large.jpg, images/sfo-1000_large.jpg, images/sfo-800_medium.jpg, images/sfo-500_small.jpg"

コードを保存し、ブラウザでページを更新します。ブラウザのデベロッパー ツールを開き、ネットワーク リクエストを確認します。別のウィンドウ サイズでページを更新してみてください。ウィンドウ サイズに関係なく、ブラウザが images/sfo-1600_large.jpg をフェッチしていることがわかります。

説明

images/ フォルダには、SFO イメージのバージョンが複数あり、それぞれ解像度が異なります。これらは srcset 属性にリストされており、使用するファイルを選択するためのブラウザがブラウザで提供されます。ただし、ブラウザでは読み込む前にファイルサイズを特定できないため、常にリストの最初の画像が選択されます。

srcset に幅記述子を追加する

ビューポートの幅に基づいて適切な画像サイズを読み込むには、各ファイルが取得する前にブラウザでサイズを通知する必要があります。

index.html で TODO 3.2 を完了するには、SFO の img 要素に幅記述子を追加します。

srcset="images/sfo-1600_large.jpg 1600w, images/sfo-1000_large.jpg 1000w, images/sfo-800_medium.jpg 800w, images/sfo-500_small.jpg 500w"

コードを保存し、ブラウザでページを更新します。さまざまなウィンドウ サイズでページを更新し、ネットワーク リクエストで各サイズで取得される画像のバージョンを確認します。1x ディスプレイの場合、ウィンドウが 500 ピクセルより狭い場合、ブラウザは sfo-500_small.jpg を取得し、幅が 800 ピクセル未満の場合は sfo-800_medium.jpg を取得します。

注: ブラウザ(HTTP)のキャッシュにより大きい画像がある場合は、srcset で指定された画像ではなくても、一部のブラウザでその画像が読み込まれることがあります(ブラウザにローカルに保存されている画像がすでに存在する場合は、使用しないでください)。このラボでこの機能を無効にするには、デベロッパー ツールで HTTP キャッシュが無効になっていることを確認します。

注: Chrome では、DevTools を開いた状態で、ブラウザのウィンドウのサイズが変更されます(下の画像を参照)。この機能は、この Codelab を通して非常に役立ちます。

chrome-dimensions.png

説明

srcset の各ファイルに幅記述子を追加することで、画像を取得するにブラウザごとに各画像の幅を伝えています。ブラウザはこれらの幅を使用して、ウィンドウ サイズに基づいて取得する画像を決定します。ビューポートの幅よりも小さい最小の幅の画像を取得します。

注: 必要に応じて、幅ではなくピクセル密度を指定することもできます。ただし、同じ srcset 属性にピクセル密度と幅の両方を指定することはできません。ピクセル密度の使用については、後のセクションで説明します。

ビューポートの半分(50 vw)の幅で画像を表示する

styles/main.css の TODO 4.1 を次のコードで置き換えます。

img#sfo {
  transition: width 0.5s;
  max-width: 50vw;
}

コードを保存し、ブラウザでページを更新します。さまざまなウィンドウ サイズでページを更新し、各サイズでネットワーク リクエストを確認してみてください。ブラウザは以前と同じサイズの画像を取得します。

説明

CSS は実行時に HTML の後に解析されるため、ブラウザは画像を取得する際の最終的な表示サイズを知ることができません。別途指定しない限り、ブラウザは画像がビューポートの幅の 100% に表示されると想定し、これに基づいて画像を取得します。画像が別のサイズで表示されるかどうかを事前にブラウザに通知する方法が必要です。

画像にサイズ属性を追加する

imgsizes 属性を指定することで、画像の取得前にブラウザにその表示サイズを通知できます。

index.html で TODO 4.2 を完成させるには、img 要素に sizes="50vw" を追加して、次のようになります。

<img id="sfo" src="images/sfo-500_small.jpg" srcset="images/sfo-1600_large.jpg 1600w, images/sfo-1000_large.jpg 1000w, images/sfo-800_medium.jpg 800w, images/sfo-500_small.jpg 500w" sizes="50vw" alt="View from aircraft window near San Francisco airport">

コードを保存し、ブラウザでページを更新します。さまざまなウィンドウ サイズでページを更新し、毎回ネットワーク リクエストを確認します。前のステップのテストで使用したのと同じおおよそのウィンドウ サイズで、ブラウザはより小さい画像を取得していることがわかります。

説明

sizes 値は、CSS の画像 max-width の値と一致します。ブラウザには、正しい画像バージョンを選択するために必要なものがすべて揃っています。ブラウザは、独自のビューポート幅とユーザーのデバイスのピクセル密度を把握しており、ソースファイル(幅記述子を使用)とビューポートに対する画像サイズ(sizes 属性を使用)を指定しています。

詳細情報

メディアクエリを CSS に追加する

メディアクエリを使用すると、ビューポートの幅に基づいて画像のサイズをリアルタイムで変更できます。

styles/main.css の TODO 5.1 を次のコードで置き換えます。

@media screen and (max-width: 700px) {
  img#sfo {
    max-width: 90vw;
    width: 90vw;
  }
}

コードを保存し、ブラウザでページを更新します。ウィンドウを 700 ピクセル未満に縮小する(Chrome では、DevTools が開いている場合はビューポート サイズが画面に表示されます)。画像の幅は、ウィンドウ幅の 90% になります。

説明

メディアクエリでは、画面のビューポートの幅をテストし、ビューポートの幅が 700 ピクセル未満の場合は CSS を適用します。

詳細情報

サイズ属性にメディアクエリを追加する

sizes 属性のメディアクエリをブラウザに通知することで、画像のサイズを変更したときに正しい画像を取得できます。

index.html で TODO 5.2 を完了するには、SFO イメージの sizes 属性を更新します。

sizes="(max-width: 700px) 90vw, 50vw"

コードを保存し、ブラウザでページを更新します。ブラウザ ウィンドウを幅 600 ピクセルに変更します。1x ディスプレイの場合、ブラウザは sfo-800_medium.jpg を取得します。

picture 要素と source 要素をメディアクエリと組み合わせて使用することで、ウィンドウのサイズを変更したときに画像ソースを変更できます。

index.html の TODO 6 を次のコードで置き換えます。

<figure>
    <picture>
    <source media="(min-width: 750px)"
            srcset="images/horses-1600_large_2x.jpg 2x,
                    images/horses-800_large_1x.jpg" />
    <source media="(min-width: 500px)"
            srcset="images/horses_medium.jpg" />
    <img src="images/horses_small.jpg" alt="Horses in Hawaii">
    </picture>
    <figcaption>Horses in Hawaii</figcaption>
</figure>

コードを保存し、ブラウザでページを更新します。ブラウザ ウィンドウのサイズを変更してみます。画像が 750 ピクセルと 500 ピクセルに変化します。

説明

picture 要素を使用すると、source タグを使用して複数のソースファイルを定義できます。これは、単に srcset 属性のある img タグを使用するのとは異なります。ソースタグを使用すると、メディアクエリなどを各ソースセットに追加できます。ブラウザに対して画像サイズを指定し、使用するファイルを決定する代わりに、使用するウィンドウ サイズごとに画像を定義できます。

サンプル画像には複数のバージョンがあり、それぞれ解像度が異なるため、小さいサイズで画像のピントが合うように切り抜かれています。上記のコードでは、750 ピクセルを超えるブラウザでは、horses-1600_large_2x.jpg(デバイスに 2x ディスプレイがある場合)または horses-800_large_1x.jpg を取得します。ウィンドウの幅が 750 ピクセル未満で 500 ピクセルを超える場合、ブラウザは horses_medium.jpg を取得します。500 ピクセル未満の場合、ブラウザは代替画像 horses_small.jpg を取得します。

注: ユーザーのブラウザが picture 要素をサポートしていない場合は、img 要素の内容をすべて取得します。picture 要素は、それに含まれる img 要素の複数のソースを指定するためにのみ使用されます。img 要素は画像を表示する要素です。

詳細情報

ウェブサイトの画像をあらゆるデバイスで美しく表示する方法を学びました。

リソース

プロセスの自動化の詳細

srcset と size の詳細

アート ディレクションの詳細

PWA トレーニング コースのすべての Codelab については、コースのようこそ Codelab をご覧ください。