この翻訳は不完全です。英語から この記事を翻訳 してください。

この記事では、レスポンシブ画像の概念 — 画面サイズ、解像度などの機能が大きく異なる機器で適切に動作する画像 — について学び、 HTML がそれを実装する上でどのような道具を提供しているかを見てみます。レスポンシブ画像は、レスポンシブウェブデザインの一部にすぎませんが (そしてそれを実現する上で良いステージになりますが)、 CSS のトピックの将来のモジュールで多くのことを学ぶトピックです。

前提: HTML の基本及びウェブページに静止画を追加する方法をすでに知っているものとします。
目的: srcset<picture> 要素のような機能を使って、ウェブサイトにレスポンシブ画像を実装する方法を学ぶこと。

なぜレスポンシブ画像なのか

では、レスポンシブ画像でどのような問題を解決しようとしているのでしょうか。典型的なシナリオを見てみましょう。典型的なウェブサイトには、おそらく訪問者の印象を良くするためのヘッダー画像と、おそらくその下にはコンテンツ画像がいくつかあります。おそらく、ヘッダー画像はヘッダーの幅全体にまたがるようにして、コンテンツ画像はコンテンツ列のどこかに合わせたいと思うでしょう。この簡単な例を見てみましょう。

広い画面で表示されているサイト例 - ここでは最初の画像はよく、中央で細部まで十分に見えます。

これは、ノート PC やデスクトップなどの画面が広機器ではうまく表示できます (ライブを見て、 Github でソースコードを見ることができます。) 以下の点を除けば CSS については詳しく説明しません。

  • 本文のコンテンツは、最大幅1200ピクセルに設定されています。 — その幅を超えるビューポートでは、本体は1200ピクセルのままで、利用可能な領域の中で中央に配置されます。それよりも狭いビューポートでは、本文はビューポートの幅の100%になります。
  • ヘッダー画像は、ヘッダーの幅がどのような幅であっても、その中心が常にヘッダーの中央に来るように設定されています。ですから、サイトがより狭い画面で表示されている場合は、画像の中心にある重要なディテール (人物) が常に見え、両端の余分な部分が失われます。高さは200ピクセルです。
  • コンテンツ画像は、 <body> 要素が画像より狭くなると、画像があふれるのではなく、常に本文内に収まるように縮小し始めるよう設定されています。

これは問題ありませんが画面が狭い機器でサイトを表示するときには問題が発生します。 — ヘッダーは正しく見えますが、モバイル機器の画面の高さ全体のうち多くの部分を占めるようになってきています。最初のコンテンツ画像はひどく見えにくくなっています。 — この寸法では、中の人物がほとんど見えていません。

狭い画面で見たサイト例。最初の画像は細部が分かりにくいところまで縮小しています。

狭い画面、及びおそらくタブレットのような中ぐらいの幅の画面の機器でも、サイトを見たときには、写真の中の重要な部分を切り抜いて表示したほうがはるかにいいでしょう。 — これは一般に、アートの向きの問題として知られています。

さらに、小さなモバイル画面で見ている場合、このような大きな画像をページに埋め込む必要はありません。これは解像度切り替えの問題と呼ばれています。 — ラスター画像は幅のピクセルの集まりと、高さのピクセルの集まりです。元の寸法よりも大きく表示されたとき、ベクター画像を見ると、ラスター画像は粗くひどく見え始めるでしょう (ベクター画像はそうではないのに対して)。また、元の寸法よりも大幅に小さく表示されると、通信帯域の無駄遣いになります。 — モバイルの利用者は、機器が小さい画像を使用するとき、デスクトップ向けの巨大な画像をダウンロードすることで帯域を占用させたくないでしょう。複数の解像度を利用可能にし、ウェブサイトにアクセスするさまざまな機器のそれぞれに適切な寸法を提供することができるのが理想的です。

状況をより複雑にしているのが、一部の機器は高い解像度の画面を持ち、きれいに表示するには、期待されるよりも大きい画像を必要としていることです。これは本質的に同じ問題ですが、少し異なる状況のものです。

ベクター画像はある側面でこれらの問題を解決すると思うかもしれません。 — ファイルサイズが小さくて容易に拡縮でき、どこでも利用できるからです。しかし、すべての種類の画像に適しているわけではありません。 — 単純な図形、パターン、インターフェイス要素などには適していますが、例えば写真のような、詳細なものをベクターベースの画像で作成すると、とても複雑になります。 JPEG のようなラスター画像形式は、上記の例に見られるような種類の画像により適しています。

この種の問題は、ウェブが最初に登場したとき、90年代前半から中期の頃には存在しませんでした — ウェブをブラウズする唯一の機器はデスクトップとノート PC であったため、ブラウザーの技術者や仕様書の著者は解決策を実装することを考えませんでした。レスポンシブ画像技術は上記のような問題を解決するために最近になって実装され、ブラウザーに様々な画像ファイル、どれも表示するものは同じですが、ピクセル数が異なる様々な画像 (解像度の切り替え)、異なる領域の取り方が異なる様々な画像 (アートの向き) を含めることができます。

メモ: この記事で説明している新機能 — srcset/sizes/<picture> — は、最近のデスクトップ及びモバイルのブラウザーのすべてが対応しています (Microsoft Edge ブラウザーも含みますが Internet Explorer は含みません)。

レスポンシブ画像の作り方

この節では、上で説明した二つの問題を踏まえ、 HTML のレスポンシブ機能を使用してそれらを解決する方法を示します。なお、上記の例のコンテンツエリアに見られるように、この節では HTML の <img> に注目します。 — サイトヘッダーの画像は単なる装飾なので、 CSS 背景画像を使用して実装します。 CSS はおそらく、 HTML よりもレスポンシブデザインのための優れたツールを持っていますので、これについては将来 CSS のモジュールで説明します。

解像度の切り替え: 様々な寸法

それでは、解像度切り替えで解決したい問題は何でしょうか。同じ画像コンテンツを、機器に応じて大きくしたり小さくしたりして表示することです。 — これは、例の中の二番目のコンテンツ画像の状況です。標準的な <img> 要素は、伝統的にブラウザーにソースファイルを一つだけしか指定できません。

<img src="elva-fairy-800w.jpg" alt="妖精の衣装を着たエルバ">

しかし、複数の追加のソース画像と、ブラウザーが正しいものを選択する助けになるヒントを提供することができる、新しい二つの属性 — srcset 及び sizes — を使用することができます。この例は、 Github の responsive.html で見ることができます (ソースコードも参照してください)。

<img srcset="elva-fairy-320w.jpg 320w,
             elva-fairy-480w.jpg 480w,
             elva-fairy-800w.jpg 800w"
     sizes="(max-width: 320px) 280px,
            (max-width: 480px) 440px,
            800px"
     src="elva-fairy-800w.jpg" alt="妖精の衣装を着たエルバ">

srcset 及び sizes 属性は複雑に見えますが、上記のように属性値のそれぞれの部分を別々の行に書けば、理解することは難しくありません。それぞれの値にはコンマ区切りのリストが設定されており、それぞれのリストの部分は3つの部分からなっています。それぞれの中身を見てみましょう。

srcset は、ブラウザーが選択することができる画像のセットと、それぞれの画像の寸法を定義します。それぞれのコンマの前に書くものは以下の通りです。

  1. 画像ファイル名 (elva-fairy-480w.jpg)
  2. 空白
  3. 画像の本質的な幅のピクセル数 (480w) — なお、これは単位に px ではなく w を使用します。これは画像の実際の寸法で、これはコンピューターの画像ファイルを調べると分かります (例えば Mac では Finder で画像を選択して、 Cmd + I を押すと情報画面が出てきます)。

sizes は、一連のメディア条件 (例えば画面の幅) であり、特定のメディア条件が成立したときに、どの寸法の画像を選択するのが最適化を示します。 — これらは以前に説明したヒントです。この場合、それぞれのコンマの前には次のようなものを書きます。

  1. メディア条件 ((max-width:480px)) — これについては CSS の記事で詳しく学びますが、今はメディア条件とは画面がなることができる状態であるとだけ言っておきましょう。この場合、「ビューポートの幅が480ピクセル以下であるとき」と言っています。
  2. 空白
  3. メディア条件が成立したときに埋めるスロットの幅 (440px)

メモ: スロットの幅については、絶対的な長さ (px, em) 又は相対的な長さ (パーセント値など) で指定することができます。最後のスロットの幅にはメディア条件がないことに気づいたかもしれません。 — これは成立するメディア条件がない場合に使用される既定値です。ブラウザーは最初に一致した条件の後はすべて無視しますので、メディア条件の順序に注意してください。

So, with these attributes in place, the browser will:

  1. Look at its device width.
  2. Work out which media condition in the sizes list is the first one to be true.
  3. Look at the slot size given to that media query.
  4. Load the image referenced in the srcset list that most closely matches the chosen slot size.

And that's it! So at this point, if a supporting browser with a viewport width of 480px loads the page, the (max-width: 480px) media condition will be true, therefore the 440px slot will be chosen, so the elva-fairy-480w.jpg will be loaded, as its inherent width (480w) is the closest to 440px. The 800px picture is 128KB on disk whereas the 480px version is only 63KB — a saving of 65KB. Now imagine if this was a page that had many pictures on it. Using this technique could save mobile users a lot of bandwidth.

Older browsers that don't support these features will just ignore them, and go ahead and load the image referenced in the src attribute as normal.

Note: In the <head> of the document you'll find the line <meta name="viewport" content="width=device-width">: this forces mobile browsers to adopt their real viewport width for loading web pages (some mobile browsers lie about their viewport width, and instead load pages at a larger viewport width then shrink the loaded page down, which is not very helpful for responsive images or design. We'll teach you more about this in a future module.)

便利な開発者ツール

There are some useful developer tools in browsers to help with working out the necessary slot widths, etc, that you need to use. When I was working them out, I first loaded up the non-responsive version of my example (not-responsive.html), then went into Responsive Design View (Tools > Web Developer > Responsive Design View), which allows you to look at your web page layouts as if they were being viewed through a variety of different device screen sizes.

I set the viewport width to 320px then 480px; for each one I went into the DOM Inspector, clicked on the <img> element we are interested in, then looked at its size in the Box Model view tab on the right hand side of the display. This should give you the inherent image widths you need.

A screenshot of the firefox devtools with an image element highlighted in the dom, showing its dimensions as 440 by 293 pixels.

Next, you can check whether the srcset is working by setting the viewport width to what you want (set it to a narrow width, for example), opening the Network Inspector (Tools > Web Developer > Network), then reloading the page. This should give you a list of the assets that were downloaded to make up the webpage, and here you can check which image file was chosen for download.

Note: When testing in Chrome, disable the cache when DevTools is open by checking the box under Settings > Preferences > Network. Otherwise, Chrome will favor cached images over better-fitting ones.

a screenshot of the network inspector in firefox devtools, showing that the HTML for the page has been downloaded, along with three images, which include the two 800 wide versions of the responsive images

Resolution switching: Same size, different resolutions

If you're supporting multiple display resolutions, but everyone sees your image at the same real-world size on the screen, you can allow the browser to choose an appropriate resolution image by using srcset with x-descriptors and without sizes — a somewhat easier syntax! You can find an example of what this looks like in srcset-resolutions.html (see also the source code):

<img srcset="elva-fairy-320w.jpg,
             elva-fairy-480w.jpg 1.5x,
             elva-fairy-640w.jpg 2x"
     src="elva-fairy-640w.jpg" alt="Elva dressed as a fairy">

A picture of a little girl dressed up as a fairy, with an old camera film effect applied to the imageIn this example, the following CSS is applied to the image so that it will have a width of 320 pixels on the screen (also called CSS pixels):

img {
  width: 320px;
}

In this case, sizes is not needed — the browser simply works out what resolution the display is that it is being shown on, and serves the most appropriate image referenced in the srcset. So if the device accessing the page has a standard/low resolution display, with one device pixel representing each CSS pixel, the elva-fairy-320w.jpg image will be loaded (the 1x is implied, so you don't need to include it.) If the device has a high resolution of two device pixels per CSS pixel or more, the elva-fairy-640w.jpg image will be loaded. The 640px image is 93KB, whereas the 320px image is only 39KB.

Art direction

To recap, the art direction problem involves wanting to change the image displayed to suit different image display sizes. For example, if a large landscape shot with a person in the middle is shown on a website when viewed on a desktop browser, then shrunk down when the website is viewed on a mobile browser, it will look bad as the person will be really tiny and hard to see. It would probably be better to show a smaller, portrait image on mobile, which shows the person zoomed in. The <picture> element allows us to implement just this kind of solution.

Returning to our original not-responsive.html example, we have an image that badly needs art direction:

<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">

Let's fix this, with <picture>! Like <video> and <audio>, The <picture> element is a wrapper containing several <source> elements that provide several different sources for the browser to choose between, followed by the all-important <img> element. The code in responsive.html looks like so:

<picture>
  <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
  <source media="(min-width: 800px)" srcset="elva-800w.jpg">
  <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">
</picture>
  • The <source> elements include a media attribute that contains a media condition — as with the first srcset example, these conditions are tests that decide which image is shown — the first one that returns true will be displayed. In this case, If the viewport width is 799px wide or less, the first <source> element's image will be displayed. If the viewport width is 800px or more, it'll be the second one.
  • The srcset attributes contain the path to the image to display. Note that just as we saw with <img> above, <source> can take a srcset attribute with multiple images referenced, and a sizes attribute too. So you could offer multiple images via a <picture> element, but then also offer multiple resolutions of each one too. Realistically, you probably won't want to do this kind of thing very often.
  • In all cases, you must provide an <img> element, with src and alt, right before </picture>, otherwise no images will appear. This provides a default case that will apply when none of the media conditions return true (you could actually remove the second <source> element in this example), and a fallback for browsers that don't support the <picture> element.

This code allows us to display a suitable image on both wide screen and narrow screen displays, as shown below:

Our example site as viewed on a wide screen - here the first image works ok, as it is big enough to see the detail in the center.Our example site as viewed on a narrow screen with the picture element used to switch the first image to a portrait close up of the detail, making it a lot more useful on a narrow screen

Note: You should use the media attribute only in art direction scenarios; when you do use media, don't also offer media conditions within the sizes attribute.

Why can't we just do this using CSS or JavaScript?

When the browser starts to load a page, it starts to download (preload) any images before the main parser has started to load and interpret the page's CSS and JavaScript. This is a useful technique, which on average has shaved 20% off page load times. However, it is not helpful for responsive images, hence the need to implement solutions like srcset. You couldn't for example load the <img> element, then detect the viewport width with JavaScript and dynamically change the source image to a smaller one if desired. By then, the original image would already have been loaded, and you would load the small image as well, which is even worse in responsive image terms.

Use modern image formats boldly

There are several exciting new image formats (such as WebP and JPEG-2000) that can maintain a low file size and high quality at the same time. However, browser support is spotty.

<picture> lets us continue catering to older browsers. You can supply MIME types inside type attributes so the browser can immediately reject unsupported file types:

<picture>
  <source type="image/svg+xml" srcset="pyramid.svg">
  <source type="image/webp" srcset="pyramid.webp"> 
  <img src="pyramid.png" alt="regular pyramid built from four equilateral triangles">
</picture>
  • Do not use the media attribute, unless you also need art direction.
  • In a <source> element, you can only refer to images of the type declared in type.
  • As before, you're welcome to use comma-separated lists with srcset and sizes, as needed.

Active learning: Implementing your own responsive images

For this active learning, we're expecting you to be brave and go it alone ... mostly. We want you to implement your own suitable art directed narrow screen/wide screen shot using <picture>, and a resolution switching example that uses srcset.

  1. Write some simple HTML to contain your code (use not-responsive.html as a starting point, if you like)
  2. Find a nice wide screen landscape image with some kind of detail contained in it somewhere. Create a web-sized version of it using a graphics editor, then crop it to show a smaller part that zooms in on the detail, and create a second image (about 480px wide is good for this.)
  3. Use the <picture> element to implement an art direction picture switcher!
  4. Create multiple image files of different sizes, each showing the same picture.
  5. Use srcset/size to create a resolution switcher example, either to serve the same size image at different resolutions, or different image sizes at different viewport widths.

Note: Use the browser devtools to help work out what sizes you need, as mentioned above.

まとめ

That's a wrap for responsive images — we hope you enjoyed playing with these new techniques. As a recap, there are two distinct problems we've been discussing here:

  • Art direction: The problem whereby you want to serve cropped images for different layouts — for example a landscape image showing a full scene for a desktop layout, and a portrait image showing the main subject zoomed in close for a mobile layout. This can be solved using the <picture> element.
  • Resolution switching: The problem whereby you want to serve smaller image files to narrow screen devices, as they don't need huge images like desktop displays do — and also optionally that you want to serve different resolution images to high density/low density screens. This can be solved using vector graphics (SVG images), and the srcset and sizes attributes.

This also draws to a close the entire Multimedia and embedding module! The only thing to do now before moving on is to try our multimedia assessment, and see how you get on. Have fun.

関連項目

ドキュメントのタグと貢献者

このページの貢献者: mfuji09
最終更新者: mfuji09,