srcsetとsizesで画像の種類とサイズを使い分ける(レスポンシブルデザイン)
srcset属性で画面幅ごとに表示する画像を選択でき、sizes属性で画面幅ごとに表示する画像のサイズを選択できます。
記述子を「w」で指定する場合、解像度は「1x」で計算されるので、Retinaディスプレイ向けの2x時の画像指定をするべきです。
割合指定は全て画像の幅に対してではなく画面の幅を100%とした場合の割合である事に注意しましょう。
レスポンシブルデザインでは必須の画像出し分け
レスポンシブルデザインのWEBサイトを構築する際に一番のネックとなるのが画像です。
一般的に画像を用意する場合、SVG画像などでない限り「作成時点のサイズ」がありますよね。
しかし現在の主流は、モニターサイズに応じて画像の表示サイズが変わるWEBサイトです。
作成時には鮮明な画像でもサイズが都度変わる訳ですから、それが維持されるとは限らないのですね。
画面幅ごとに画像を用意する
現在はそのデバイスごとに最適な画像をそれぞれ用意し、端末に応じて表示画像を切り替えるのがセオリーです。
特にiPhone等の高解像度デバイス(Retinaディスプレイ等)では、2倍サイズの画像を用意する必要がある事はご存じでしょう。
使い回せる場合もある
例えばPCで640p幅の枠内に画像を敷き詰める場合、iPhoneでは倍の解像度が必要なので1280px画像を用意するのがセオリーです。
しかしiPhoneのメイン画面幅は2分の1の320pxでした(今はそれ以上も多いです)。
320pxの2倍あれば良いので、そのまま640pxの画像が使えます。
現在はiPhoneも画面幅が大きくなってきているので単純な使い回しでは全てカバーはできません。
様々な端末環境がある以上、今後はより綿密に対応していく事が必要になります。
CSSではなくHTMLソースに書く
このような画像の表示分岐に使う要素が「srcset属性」です。
対象が背景画像ならばCSSに頼るのですが、今回はHTMLに直接設置するimgタグに対して作用しなければなりません。
本記事ではimgタグにsrcset属性を追加する事で、htmlタグ上で複数画像を出し分ける方法をご紹介します。
srcsetの書き方
srcsetはimgタグ以外にpictureタグ内のsourceタグでも使えますが、今回はimgタグで解説します。
srcsetは、画像パスと記述子(デスクリプタ)を1セットとします。
srcsetのコード
srcset="画像パス1 記述子1,画像パス2 記述子2,画像パス3 記述子3" src=""…
画像パスと記述子の間は半角スペースを空けましょう。
上記の様にカンマで区切る事で、複数の条件が指定できます。
※src=""やalt=""、srcset=""を書く順番は自由です。
記述子とは
記述子とは画像を読み込む条件を指定する単位です。
単位はビューポート (ブラウザ表示領域) の横幅「w」や、デバイスピクセル比を表す「x」があります。
srcsetに書く場合は、記述子はどちらかで統一しましょう。
srcsetのメリット
このsrcsetのメリットは、必要のない画像はダウンロードしない点です。
条件に一致する画像のみを読込するので負担が少なくなります。
表示速度UPや処理負担の軽減はSEOの面でも大きな役割を果たします。
通常用と2倍の解像度用に画像を切り替える
以下より具体的な事例を紹介していきます。
通常のPC版とスマホなどのRetinaディスプレイ版とで別々の画像を出し分ける場合、下記のように記載します。
srcset書き方サンプル1
<img srcset="images/img_example1.jpg 1x, images/img_example2.jpg 2x" src="images/img_example.jpg" alt="">
サンプル1は、デバイスピクセル比(解像度の大きさ)にあわせて別々の画像を読み込む指定です。
1xが通常の解像度、2xがRetinaディスプレイなど2倍の解像度を示しています。
1x…通常の解像度
2x…2倍の解像度(Retinaディスプレイ)
上記の場合、通常のデバイスならimg_example1.jpgが、2倍の解像度であるRetinaディスプレイではimg_example2.jpgが読み込まれます。
画像の名前につく@1xや@2xは?
よく画像の名前自体に、@2xなどが付いている画像がありますよね。
これは画像が「通常解像度向け」なのか「2倍解像度向け」なのかが名前から判別できる様にするための工夫です。
例えば2倍の解像度向けなら「img_example@2x.jpg」等としていれば、画像一覧からすぐに2倍解像度向け画像を探す事ができます。
名前を付けただけでは出し分けはできませんので、ちゃんとsrcsetを書く必要があります。
通常のsrcは滑り止め
その後ろには通常のsrc="画像パス"が入っています。
これはsrcset=""に対応していないブラウザ等では、src=""が滑り止めとして読み込まれます。
srcsetが機能すれば、このsrcの画像パスは読み込まれません。
モニター幅(ビューポート)に応じて画像を切り替える
次に画面枠の幅に応じて表示する画像を選択するコードです。
srcset書き方サンプル2
<img srcset="img/img_example320.jpg 320w, img/img_example640.jpg 640w" src="img/img_example.jpg" alt="">
ここでの320wや640wは、幅(width)が320pxや640pxの場合を示しています。
条件分岐内容
上記コードは以下の条件に応じて切り替えをしています。
モニター幅が320pxまでなら、img_example320.jpgを読み込む
モニター幅が640pxまでなら、img_example640.jpgを読み込む
それ以外(640px以上の場合)は、img_example640.jpgを読み込む
要は「320px以下」と「それ以外」という2つの分岐です。
解像度も把握できる
srcset属性の記述子「~w」を使っている場合、解像度は「1x」として計算されています。
Retinaディスプレイの解像度は2倍ですから、幅320pxのiPhone端末の解像度は2倍の640pxですよね。
上記コードの場合「640w」が判定され、幅320pxスマホ画面でもimg_example640.jpgが読み込まれます。
もしこの640wの記述が無かったら、320px以下のiPhoneでは画像が表示されません。
320wと640wとを併用する事で、デバイスピクセル比の1x・2xの役目も果たしている事になります。
sizes属性でサイズをコントロール
これまでは端末幅に対して「どの画像を表示させるか」の選択でした。
sizes属性を使えば、その場面に応じた表示画像のサイズも指定する事ができます。
srcsetは画像ファイル自体の切り替えを担うのに対し、sizesは表示サイズを変化させる役割を担っています。
srcset書き方サンプル3
<img srcset="img/img_example1440.jpg 1440w, img/img_example720.jpg 720w" sizes="50vw" src="img/img_example.jpg" alt="">
この場合、表示サイズは常に「画面枠」の50%のサイズになります(単位は下で説明します)。
700pxのモニター枠の場合
この場合img_example720.jpgが使われ、かつ枠幅半分の350pxで表示されます。
1290pxのモニター枠の場合
この場合img_example1440.jpgの画像が選択され、かつ枠幅半分の645pxの横幅サイズで表示されます。
1800pxのモニター枠の場合
この場合img_example1440.jpgの画像が選択され、かつ枠幅半分の900pxの横幅サイズで表示されます。
sizesの記述ルール
・sizes属性は「画像の幅」ではなく「画面幅」に対して計算される
・sizes属性は、srcset属性がある場合のみ記述できる
・sizesを利用する時はsrcsetの記述子は必ず「w」単位で書く
sizessの基準は「画面枠」
例えば、1920pxの画面枠と1200px幅の画像があったとします。
sizesが50vwとしてあった場合、表示サイズは画像サイズの半分で600pxではなく、枠の半分の960pxになる事に注意しましょう。
ここが一番誤解されやすいところだと思います。
大きさ単位
sizesで指定できる大きさは「em、rem、px、cm、pt」など様々な単位が使用できます。
calc()など関数を利用した長さ指定もできます。
割合指定
サイズを割合で指定したい場合、sizesでは%指定ができません。
代わりに、ビューポート(ブラウザ幅)に対する割合を示す単位が別に用意されています。
vw…ビューポートの横幅の長さを100%とした割合
vh…ビューポートの縦の長さを100%とした割合
vmin…ビューポート縦横のどちらか小さい方に対する割合
vmax…ビューポート縦横のどちらか大きい方に対する割合
スマホの場合、vwとvhは縦向き (ポートレートモード) と横向き (ランドスケープモード) によって算出される数値が変化します。
vmin・vmax
vmin指定はビューポートが「360x600px」なら、短い方の360pxが算出基準となります。
10vminなら「36px」の横幅で表示
100vminなら「360px」幅一杯の表示
vmax指定はビューポートが「360x600px」なら、長い方の600pxが算出基準となります。
条件分岐によるsizes属性のコントロール
srcset書き方サンプル4
<img srcset="img_example1440.jpg 1440w, img_example720.jpg 720w, img_example360.jpg 360w" sizes="(max-width: 360px) 100vw,(max-width: 800px) 75vw,50vw" src="img_example.jpg" alt="">
上記サンプルを解説していきます。
モニター枠が360pxまでの場合
画像はimg_example360.jpgが使われ、幅一杯(100vw)まで広がります。
モニター枠が361~800pxまでの場合
この場合ビューポート幅の75%の横幅サイズまで広がります。
例えばモニター枠が600pxなら、img_example720.jpgの画像が使われ、幅は450pxになります。
例えばモニター枠が750pxなら、img_example1440.jpgの画像が使われ、幅は562.5pxになります。
メディアクエリなしの50vw
50vwにはメディアクエリが指定されていません。
それまでのメディアクエリに当てはまらない時に適用されるので、ビューポート幅が801px以上の場合に適用されます。
例えばビューポート幅が900pxなら、img_example1440.jpgの画像が使われ、幅は画面枠半分の450pxになります。
ここが480pxとしてあった場合
もしここが50vwではなく「480px」としてあった場合がどうなるのでしょう。
ビューポート幅が801px以上なら画面枠を480pxと考えて、最適な画像を選択する事になります。
まとめ
srcsetとsizesは複雑でややこしいため、初心者は理解するのが大変かと思います。
ポイントは2つあると思います。1つずつ紹介しましょう。
srcsetの条件分岐は「数値まで~」で把握する
条件分岐が複数つくと混乱しそうですが、A条件~320w,B条件~960w,C条件~1440wと書いてあった場合でおさらいしておきます。
0wから一番小さい数字(320w)までがA条件
321wから次に小さい数字(960w)までの間がB条件
961wから次に小さい数字(1440w)までの間がC条件
1441w以上も全てC条件が適用される
注意点
一番小さい数字は0wからその数字までで把握する事です。
数字に+1した数字から次に小さい指定数字までを区分けします。
一番大きい指定数字以降も、最後の条件が適用され続ける事になります。
条件がどれだけ増えてもこのルールに変わりはありません。
sizesの割合指定について
特にsizesの割合指定は、画像幅を100%とするのではなく画面幅(ビューポート幅)を100%とした割合です。
幅800pxの画像が50vwで400px幅になるのではありません。その時のビューポート幅の50%になるのです。
特に間違いやすいところなので注意しましょう。