KIA KING - EVERYTHING IS POSSIBLE

HTMLのsrcsetを使って画像をレスポンシブにRetina対応させてみよう

WEBでレスポンシブ対応するときに結構大変なのが画像の扱い。iPhone等の高解像度デバイス(Retinaディスプレイ等)には2倍の画像を用意する必要があるし、最近は画面のサイズに会わせて画像を切り替えたい場合も多い。そんな時にHTML5のsrcsetがすこぶる便利だったのでご紹介します。

srcsetでできること

次のようなことが可能になります。

Retinaディスプレイ用に画像を切り替える

基本的な使い方は下記のような感じでimgタグに使用します。シンプルですね。

<img src="img/example-img.jpg"
     srcset="img/example-img.jpg 1x,
             img/example-img@2x.jpg 2x"
     alt="Example image">

src
これはsrcsetに対応していないブラウザへのフォールバックです。未対応のブラウザは普通にここで指定された画像を読み込みます。

srcset
今回のミソですね。コンマ区切りで画像とその画像が読み込まれる条件を指定します。上記の例では、デバイスのDPIの大きさに合わせて別々の画像を読み込むよう指定しています。通常のデバイスならexample-img.jpgが、Retinaディスプレイではexample-img@2x.jpgが読み込まれます。このとき、srcの画像は読み込まれません。

ちなみにこのサイトでもヘッダーのロゴやフッターの写真はこれを使用しています。気になる方はソースを見てみてください。

ウィンドウサイズに合わせて画像を切り替える。

上述の例では、画面サイズによらず全ての画像が単純に@2xのサイズになってしまいます。そこで、<picture>要素のsourceを使用すると、メディアクエリーを使って条件を指定できます。

<picture>
  <source media="(min-width: 320px)" srcset="small.jpg 1x, small@2x.jpg 2x">
  <source media="(min-width: 640px)" srcset="big.jpg 1x, big@2x.jpg 2x">
  <img src="small.jpg" alt="Example image">
</picture>

見た通りですが、ウィンドウサイズが320px以上ならsmall.jpgが、さらにRetinaディスプレイならsmall@2x.jpgが読み込まれます。

ウィンドウサイズに合わせて動的に画像を切り替える

さらに動的に条件を指定することができます。こっからややこしくなりますが、まずはコードを。

<img src="img/example-img.jpg"
     srcset="img/example-img-320.jpg 320w,
             img/example-img-640.jpg 640w"
     alt="Example image">

さて、このコードでなにが起きるかというと、ウィンドウサイズが320px以下ならexample-img-320.jpgが、640px以下かそれ以上ならexample-img-640.jpgが読み込まれます。

さらにこの指定のすごいのは、DPIの高さも計算に入れてくれるということです。つまり、Retinaディスプレイで見た場合、320px以下の時もexample-img-640.jpgが読み込まれます。Retniaだと解像度が2倍になるので、320 X 2 = 640ということですね。

これは画像の大きさが完全にディスプレイ依存で流動的な場合に効果を発揮します。例えば、デスクトップで見たときに640pxの画像があった場合、Retinaに対応する場合1,280pxの画像が必要ですが、同じ画像をiPhoneで見た場合、iPhoneの横幅は320pxなので640pxで十分なわけです。

そんなとき、この指定の方法なら画面サイズに合わせて画像を読み込んでくれるため、無駄が省けます。

さらにsizesと組み合わせて、画像のサイズ指定を変動させることもできます。

<img src="img/example-img.jpg"
     sizes="50vw"
     srcset="img/example-img-320.jpg 320w,
             img/example-img-640.jpg 640w"
     alt="Example image">

こうするとウィンドウサイズの半分(50vw)のサイズの画像が選択されます。どうなるかというと、今度がウィンドウサイズが640pxを超えるまでexample-img-320.jpgが読み込まれます。

ややこしいだけじゃね?という感じですが、さらにメディアクエリと組み合わせる事でウィンドウサイズに合わせて可変的なサイズを指定できます。グリッドデザインとかで効果を発揮できそうですね。

<img src="img/example-img.jpg"
     sizes="(min-width: 640px) 50vw, 100vw"
     srcset="img/example-img-320.jpg 320w,
             img/example-img-640.jpg 640w"
     alt="Example image">

こうすると、ウィンドウサイズが640px以上のときはウィンドウサイズの半分の大きさの画像を読み込み、それ以外の時は画面サイズに対して100%の画像を読み込みます。

もはやここまでくると訳が分からなくなってきますが、相当柔軟に画像を選択できるってことですな!

なにがいいの?

このsrcsetの素晴らしいのは、対応しているブラウザは必要ない画像をダウンロードしないという点です。今のところChromeが対応していますが、対応していないブラウザにも、後述のpicturefillを使って対応させることができます。

これまでの、例えばJavaScriptで後から高解像度の画像に差し替えるような方法だと、どうしてもまず低解像度の画像をダウンロードして、次に高解像度をダウンロードするというネットワークで2度の無意味な通信が発生していました。これが解決されるのは素晴らしい。

また、Retina対応だけじゃなくて、画面サイズに合わせて画像を切り替えることも出来るのもGOOD。

ところでbackground-imageはどうするの?

Media queryでやっちゃいましょう。ぶっちゃけ背景画像はかなり楽なんですよね・・・。

.img-retina {
  background-image: url("img/example-img.jpg");
  background-size: 320px 320px;
}

@media only screen and (-webkit-min-device-pixel-ratio: 2),
       only screen and (   min--moz-device-pixel-ratio: 2),
       only screen and (     -o-min-device-pixel-ratio: 2/1),
       only screen and (        min-device-pixel-ratio: 2),
       only screen and (                min-resolution: 192dpi),
       only screen and (                min-resolution: 2dppx) {
    background-image: url("img/example-img@2x.jpg");
    background-size: 320px 320px;
}

こんな感じで切り替えるべし。Retina対応させるときのcssのサンプルは色々あるみたいだけど、ここではBootstrapのものを持ってきました。

未対応ブラウザへの対応

このsrcset、まだまだ未対応のブラウザは多く、それらにはポリフィルを当ててあげないといけません。もちろんあります。その名もpicturefill。サイトからjsをダウンロードして読み込むだけでOKです。下記のコードを</body>タグの直前にでもぶちこみましょう。

<script src="js/picturefill.js"></script>

あとはなにもしなくても勝手に対応してくれます。ただ一つ問題があるとすれば、srcで指定した画像を読み込んでしまう、というところ。まぁしょうがないです。srcを指定しなければsrcsetだけを使用してくれるのですが、その場合SEO的にGoogleさんは理解してくれるのか?っていう疑問が・・・。どうなんでしょうね。

さいごに

WEBのレスポンシブ対応の大きな課題だった画像問題が解決されつつあるように思う。これまでsrcsetの他にもpicture要素とか色々なものが検討されてきていて、未だにはっきりとしていないけど、このsrcsetはかなり分かりやすくて使いやすい。

なにげにこのsrcsetを書くことより、複数の画像を用意するっていうことの方が面倒ではあるのだけども、アイコンやイラストなら今後もっとsvgが活用されるのだろうか。勉強せねば。

参照

Responsive Images Done Right: A Guide To <picture> And srcset
英語サイトですが、詳細な説明があります。