「sizes はグリッドデザインで使うと便利だよ~」というコメントを見かけたのですが、グリッドデザインについて不勉強な私にはなにが便利なのかよくわかりませんでした。ただ、sizes で表示サイズを指定できるという説明だけはちょっと違うんじゃないかなと思ったので、sizes についてまとめてみました。
きっかけ
sizes についていろいろ調べていたとき、次のように説明しているのを見かけました。
「画像を80%で表示したい場合は sizes に80vwを指定してください。」
ソースコードは次のようになります。
1 2 3 4 5 6 | <img src="test3.jpg" alt="ジンギスカン" sizes="80vw" srcset="test1.jpg 480w, test2.jpg 768w, test3.jpg 1024w"> |
これって正しいのかな?と思ったのがこの記事を書くきっかけです。
まずは実験します
sizes 属性が画像の表示サイズを指定できるという説明がおかしいというのは、簡単な実験をすればすぐにわかります。次のようなソースコードを用意します。文字コードは Shift-JIS でもよいのですが、一応 UTF-8 で。ブレイクポイントは480pxと768pxの2ヶ所に設定しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" type="text/css" href="./css/normalize.css"> <title>デモ</title> <style type="text/css"> <!-- img { width: 100%; height: auto; margin-bottom: 20px; } p { width: 100%; } .wrapper { max-width: 1024px; border: 1px #ccc solid; margin: 50px; } @media screen and (max-width: 768px) { .test { width: 100%; border: none; margin: 0; } } @media screen and (max-width: 480px) { .test { width: 100%; border: none; margin: 0; } } --> </style> </head> <body> <div class="wrapper"> <img src="test3.jpg" alt="餃子" sizes="80vw" srcset="test1.jpg 480w, test2.jpg 768w, test3.jpg 1024w"> <p> 日本の餃子は、日本で独自に進化した餃子であり、焼き餃子が主流であり(中国では水餃子が主流)、用いる具材、調理法も中国で主流のものと異なる。かつては皮も含めて家庭で材料から作ることが多かったが、皮だけ市販のものをスーパーなどで買い、具だけ作って包むという方法をとる家庭も増え、いつ頃からかは未検証だが、具を皮に包んだ状態の冷凍食品・チルド品も多種類 出回っている。各種飲食店のサイドメニューとしても広く扱われていて、焼きあがったものや生のものを持ち帰り用に販売している店もある。 </p> </div> </body> </html> |
リセット用 CSS には normalize.css を使用しました。
無料写真素材は足成さんがとても使いやすいです。3種類用意してください。理由は後述します。フルードイメージ化するので大きさはそのままでも大丈夫です。
今回は Google Chrome の検証ツールを使用しました。
先ほどの HTML ソースを読み込む前に、まずは Chrome のキャッシュを無効化にしておきます。有効なままだとなにかとトラブルのもとです。
検証ツールの右上のこの部分をクリックし、「Settings」を選択します。キーボードの F1 キーでもよいです。
「Settings」→「Preferences」→「Network」とたどってください。「Disable cache (while DevTools is open)」にチェックを入れると、検証ツールを開いている間はキャッシュが無効になります。
機種一覧から「Responsive」、Retina ディスプレイ対応を考えないので DPR は「1.0」を選択します。
DPR が表示されていない場合、ドロップダウンメニューで「Add device pixel ratio」を選んでください。
幅を小さい→大きいへ変化させていきましょう。左クリックでずんずんずんずんと横幅を広げていきます。
478、479、480、481、482・・・。あれれ。切り替わりません。
気になるでしょうが、とりあえずそのままずんずんと幅を広げていってください。601pxで切り替わるはずです。ブレイクポイントを768pxにも設定しましたが、こちらも同様の現象が起こります。961pxで切り替わると思います。
seizes に指定されたvwが画像の表示サイズを指定するだけのものであるなら、ブレイクポイントが600pxや960pxに移動しているのはおかしいはずです。
sizesとは
画像におけるレスポンシブ対応とは、srcset 属性での条件により画像を切り替えることです。今回の例で言えば480wや768wがこれにあたります。これに対し、sizes 属性は基準になる横幅を指定するだけです。
sizes に指定をする場合、vwという単位を使いますが、これは Viewport Width の略であり、描画領域の横幅を意味します。100vwであれば描画領域の100%、50vwなら50%、80vwなら80%です。
次のような srcset があったとします。
1 2 3 | <img src="img_1000.jpg" srcset="img_500.jpg 500w, img_1000.jpg 1000w"> |
ここで描画領域が1000pxで sizes=”100vw” を指定した場合、img_1000.jpg が選択されます。描画領域が1000pxで sizes=”50vw” を指定した場合、描画領域の50%で判定されるので img_500.jpg が選択されます。
今回ブレイクポイントが600pxや960pxに移動してしまいました。簡単な方程式を解いてください。600X0.8=480pxですね。
説明の間違いに気付きにくい訳
この説明の間違いに気付きにくいのにはいくつかの理由があると思います。
見た目では分かりづらい
一般的に srcset を使って画像を振り分ける場合、細かい制御を考えないのであれば次のように記述するかと思います。
1 2 3 4 5 | <img src="test_1024.jpg" alt="ローストビーフ" srcset="test_480.jpg 480w, test_768.jpg 768w, test_1024.jpg 1024w"> |
このとき用意される画像は、サイズは異なるけど映っているものは同じ画像であるはずです。そうすると、Chrome や Firefox などのテストツールで動作確認を行っても、どのブレイクポイントで画像が切り替わっているかがわかりづらいため、一見すると問題なく動作しているように感じてしまいます。
小さい画面で大きい画像から一部を切り抜いたものを表示させる「アートディレクション」の場合、見た目にかなりの違いが出るのでブレイクポイントがズレていればすぐにわかったはずです。先ほどわざわざ3種類の画像を用意して実験を行ったのはこのためです。
実際に80%の大きさで表示されることがある
いくら見た目では分かりづらいとはいっても、実際に80%で表示されていなければ異常に気付けたはずです。にもかかわらず見逃してしまった理由は、実際に80%で表示されるパターンがあるからです。
先ほどのソースコードで画像をフルードイメージ化している部分を見てください。
1 2 3 4 | img { width: 100%; height: auto; } |
ネットで調べてみると、ほとんどのサイトでは max-width を使っています。試しに width と max-width を置き換えて動作を確認してみてください。max-width で100%化した場合、sizes に80vwを指定すると表示まで80%になってしまいます。
以前記事にしましたが、画像のフルードイメージ化は width・max-width のどちらを使っても行うことができます。どっちを使っても動作は同じです。
なぜフルードイメージではmax-widthを100%にしているのか? | Naokix.net
ところが、sizes 属性に関する動作についてのみ width と max-width で挙動が異なります。目的があってビューポートの80%で画像を振り分けるのではなく、純粋に振り分け後の画像を80%で表示したいのであれば、sizes に80vwを指定せずに次のようにするべきです。
1 2 3 4 | img { width: 80%; height: auto; } |
いずれ各種ブラウザが対応してくれる可能性があり神経質にならなくてもよいのかもしれませんが、Firefox の検証ツールでも同様の現象が起きることを考えると、画像のフルードイメージ化には width を使用したほう無難であると言えます。
一応レスポンシブ対応の目的を果たしている
アートディレクションの場合には成立しませんが、複数サイズの画像を用意するレスポンシブ対応だった場合、意図したブレイクポイントではないものの、画面の小さなモバイルにはサイズの小さな画像をダウンロードさせて通信量を軽減する、という当初の目的を達成できてしまっています。
画面の小さなモバイルにも大きなサイズの画像をダウンロードさせていた場合、実機で動作確認していれば通信量の多さで気付けたかもしれません。ところが同画像複数サイズ系レスポンシブだった場合、多少ブレイクポイントがズレていてもモバイルに対しては通信量が軽減されることにかわりはなく、実機で検証を行っていても気が付かなかったのだと思います。
みんなそこまで作り込んでいない(暴言
今回画像のレスポンシブ対応についてネットでずいぶん調べたのですが、基本的な sizes の使い方にとどまるばかりで、「こうやって使うとこんなに便利なんだよ~」というサンプルにたどり着けませんでした。グリッドレイアウトに使えそうだというコメントをいくつか見かけたのですが、グリッドレイアウトについて不勉強な私にはよくわかりません。分かり次第追記ということで。
それはともかく、画像のレスポンシブ対応については最悪でもフルードイメージ、複数サイズの画像による srcset までやっておけばとりあえずは大丈夫なわけで、複数サイズの画像を用意するだけでもかなりの手間になります。
これに加えて、記事も書かなければならない、ほかの部分のデザインもレスポンシブ対応しなければならないなど、やらなければいけないことは山積みになっており、sizes の細かい使い方にまで手が回らないのではないかと推測しています。知ってる人、教えてください。
Comment