解像度とは
Retinaに代表される高解像度ディスプレイは、100〜200dpi程度だった従来のディスプレイの数倍の解像度です。ここでの解像度とは、1インチ中のピクセル数を表す密度(単位:ppi)ではなく、ディスプレイ中のピクセル数を指します。ディスプレイのピクセル数のことを画面解像度(単位:px)とも言います。
従来のディスプレイは1ドットを等倍の1ピクセルで表示していましたが、高解像度ディスプレイではそれを2px x 2pxや、3px x 3pxなどで1ピクセルを表示することにより高い解像度を実現しています。そのため、高解像度ディスプレイにおいて1pxとは、物理的な2px × 2px内の1pxなのか、擬似的な1pxなのかが不明瞭になります。そこで、ぞれぞれを区別するために、ピクセルを次のように使い分けています。
- デバイスピクセル(物理ピクセル):ディスプレイの物理的なピクセル数
- CSSピクセル(論理ピクセル):デバイスに表示させる擬似的なピクセル数
これで物理ピクセル(デバイスピクセル)なのか論理ピクセル(CSSピクセル)なのかが明瞭になりました。さらに理解しておきたいのが、デバイスピクセル比です。このデバイスピクセル比は、デバイスピクセルとCSSピクセルとの比率を表します。
たとえばデバイスピクセル比が2の場合、1つのCSSピクセルを縦2倍 x 横2倍(合計4つ)のデバイスピクセルで表示します。実際のケースを例にしてみましょう。ある端末のデバイスピクセル比が3の場合、そのディスプレイの解像度が1080px x 1920pxであれば、ブラウザ上で表示されるときには3分の1の360px x 640pxで表示されます。
高解像度ディスプレイへの対応
高解像度ディスプレイに対応する場合、倍のサイズでデザインしないとその特性が発揮されません。たとえば、横幅375ピクセルのデバイス向けにデザインする場合、横幅750ピクセルで出力する必要があります。高解像度ディスプレイに対応するには画像出力時のみではなく、コーディングでも対応が必要です。
以下を参考に対応してください。
- 表示サイズをデバイス・ピクセル比でかけた値で出力
横幅375ピクセルのデバイス向けにデザインする場合、横幅750ピクセルで出力する。 - 画像はデバイス・ピクセル比で割り切れるサイズ出力
デバイス・ピクセル比が2であれば、2で割り切れる画像サイズで出力する。
デザインでデバイス・ピクセル比で割れないサイズになっている際は、余白を含めて割り切れるサイズにして出力する。 - IMGタグのwidth属性とheight属性は画像の実サイズの半分の値を指定
backgrond-imageを使った背景場像の場合は、実サイズをデバイス・ピクセル比で割った値をbackground-sizeに指定する。
srcset属性とは
高解像度ディスプレイのコーディング対応としては、HTML5のsrcset属性が一般的です。srcset属性に表示したい画像と条件のセットを複数設定すると、閲覧環境に応じて最適な画像に切り替えます。条件にはウインドウサイズ、デバイス・ピクセル比を設定することが可能です。srcset属性の大きな利点は、状況に合わせた画像1枚が読み込まれて、その他の候補画像は読み込まれないということです。
srcsetに設定できる条件
- デバイス・ピクセル比で画像を切り替える
- ウィンドウサイズで画像を切り替える
- ウィンドウサイズに動的に合わせて画像を切り替える
srcset属性はほとんどのブラウザの最新バージョンで対応していますが、Internet explorerは未対応です。
srcset属性を指定できるタグはIMGタグとPICTUREタグ内のSOURCEタグの2種類です。
IMGタグの使用例
<img src="pic.jpg" srcset="pic@2x.jpg 2x, pic@3x.jpg 3x" alt="***">
PICTURE + SOURCEタグの使用例
<picture>
<source media="(min-width: 800px)" srcset="pic-800w.jpg">
<source media="(max-width: 799px)" srcset="pic-480w.jpg">
<img src="pic-800w.jpg" alt="***">
</picture>
IMGタグとPICTUREタグ + SOURCEタグの用途は重なっている部分もあり、2種を混在して使ってよいのか、どちらかに統一したほうが良いのかなどがわかりにくいところがあります。わかりやすい違いとしては、PICTUREタグ + SOURCEタグはIMGと比べてコード量が多くなりますが、画面解像度やウインドウサイズ以外にも、SVGやWEBPに対応しているかなどで画像の種類を分けることもできます。その違いで使い分けるとしたら、IMGタグで対応できる場合はIMG、IMGタグで対応できない場合はPICTUREタグ + SOURCEタグを使う、というのがコード量を抑えられ、かつシンプルな方法かと思います。
IMGタグとsrcset属性の使い方
srcset属性には表示したい画像URLと、条件を設定する記述子を指定します。
<img srcset="画像URL 記述子, …" src="デフォルト画像URL">
src属性
画像のパスを指定します。srcset属性が未対応のブラウザにはこの値が使われます。
srcset属性
カンマ区切りで画像URLと、その画像の読み込み条件を指定します。読み込み条件にはデバイス・ピクセル比、もしくは表示領域の横幅を指定できます。src属性よりもsrcset属性が優先されます。
デバイス・ピクセル比
<img src="pic.jpg" srcset="pic@2x.jpg 2x, pic@3x.jpg 3x" alt="***">
端末のデバイス・ピクセル比を指定するには記述子 x を使います。例えば、デバイス・ピクセル比を2とする場合は 2x、3であれば3xです。画面解像度に合わせて画像を変えたいときはデバイス・ピクセル比で指定すると良いでしょう。
表示領域の横幅(ビューポート幅)
<img src="pic.jpg" srcset="pic-1240.jpg 1240w, pic-620.jpg 620w, pic-310.jpg 310w" alt="***">
表示領域の横幅は記述子 w を使います。上記コードでは、デバイス・ピクセル比が1の場合、表示領域の横幅が310pxまではpic-310.png、620pxまでは pic-620.png、それ以上のサイズでpic-1240.pngが表示されます。デバイス・ピクセル比が2であれば、310pxでもpic-620.pngが表示され、620px以上でpic-1240.pngが表示されます。このように、表示領域の横幅を指定する記述子 w でも、デバイス・ピクセル比は自動的に考慮されます。
sizes属性
sizes属性は、srcset属性をベースに、画像を表示する際の横幅を設定します。そのため、sizes属性はsrcset属性がある場合のみ有効です。また、sizesを設定する際のsrcsetの記述子は必ず w になります。
<img sizes="50vw" srcset="pic-1240.jpg 1240w, pic-620.jpg 620w, pic-310.jpg 310w" src="pic.jpg">
上記コードでは、ビューポート幅の5割の横幅で表示され、その画像幅とデバイスピクセル比から最適なサイズの画像が呼び出されます。例えば、ビューポート幅が620pxであれば、sizesの設定により画像は5割の310pxで表示されます。そのため、srcset属性で310wの指定があるpic-310.jpgが表示されます。デバイス・ピクセル比が2の端末の場合、pic-310.jpgではなくpic-620.jpgが表示されます。
sizes属性に指定できる単位として、pxやremなどから、vw、vh、vmin、vmaxなどが使えます。
sizes属性にメディアクエリを設定
メディアクエリを使って画像の横幅を設定することもできます。メディアクエリはカンマで区切って複数指定できます。
<img sizes="(min-width: 620px) 50vw, 100vw" srcset="pic-1240.jpg 1240w, pic-620.jpg 620w" src="pic.jpg">
メディアクエリはカッコで囲み、半角スペースを空けて、画像の表示幅を指定します。上記コードでは、ウィンドウサイズが620px以上のときは画像サイズをウィンドウサイズの半分で表示し、それ以外の時はウインドウサイズに対して100%の横幅で表示します。
未対応ブラウザへの対応
Internet explorerはsrcset属性に対応していないため、IE対応が必要な際はpicturefillというポリフィル用スクリプトを読み込む必要があります。下記サイトから必要なバージョンをダウンロードして、読み込むようにしてください。
<script src="picturefill.js"></script>
picturefill.jsはCDNでも提供されているので、次のように指定できます。
<script src="https://cdnjs.cloudflare.com/ajax/libs/picturefill/3.0.3/picturefill.min.js"></script>
ポリフィルは読み込むだけでOKです。これで表示上の問題は解決できますが、ポリフィルが使われる環境では条件に関わらずsrcで指定した画像も読み込まれてしまいます。
背景画像で高解像度ディスプレイに対応
背景画像にはsrcsetが使えないので、メディアクエリで対応します。
.site-logo {
width: 200px;
height: 100px;
background: url(logo.png) no-repeat;
background-size: 100%;
text-indent: -9999px;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
#logo {
background-image: url(logo@2x.png);
}
}
上記コードはデバイス・ピクセル比が2の場合は背景画像をlogo@2x.pngに差し替えています。