srcsetとsizes
パート1:メディア・クエリのどこがまずいのか?
そう、もし君がウェブサイトを作っている時代が1993年2月23日から2010年5月25日の間だったら、画像の扱いなんてチョロかったね! それはこんなふうに単純だった。
●幅の固定されたレイアウトをにらみつける
●画像がきっかり何ピクセルかを測る――その画像はあらゆるユーザーの画面で変わらないスペースを占めることになる
●Photoshopのエンジンをかける
●画像をさっき測ったとおりのサイズで﹁ウェブ用に保存﹂する
●それを



ときおり聡明なる預言者が荒野から現れては、この手法に潜む問題について深遠な真実を説くこともあった。それでもこのやり方は、20年もの間、ウェブ・デザイナーを生業とするものたちに受け入れられてきた。
しかし、時代は変わる。
、イーサン・マーコットがある記事を書いた。、スティーヴ・ジョブズはある携帯電話を発表した。突如として﹁フルード︵流動的︶﹂で﹁レティナ︵高精細︶﹂な画像が重要になった。そしてそれ以来、そこらじゅうから歯ぎしりが聞こえてくる。
<img>タグでマークアップする
●グラスにビールを注ぎ︵または新鮮なグリンピースの缶を開け︶、仕事がうまくいったことを祝う



ときおり聡明なる預言者が荒野から現れては、この手法に潜む問題について深遠な真実を説くこともあった。それでもこのやり方は、20年もの間、ウェブ・デザイナーを生業とするものたちに受け入れられてきた。
しかし、時代は変わる。
、イーサン・マーコットがある記事を書いた。、スティーヴ・ジョブズはある携帯電話を発表した。突如として﹁フルード︵流動的︶﹂で﹁レティナ︵高精細︶﹂な画像が重要になった。そしてそれ以来、そこらじゅうから歯ぎしりが聞こえてくる。
| 変数 | 製作者が コードを書くとき | ブラウザーが ページを読み込むとき |
|---|---|---|
| ビューポートの寸法 | 知らない | 知ってる |
| ビューポートに対する画像の相対的な幅 | 知ってる | 知らない |
| 画面密度 | 知らない | 知ってる |
| ソース・ファイルの寸法 | 知ってる | 知らない |
一方が﹁知ってる﹂のとき、もう一方は必ず﹁知らない﹂である点に注目! 製作者とブラウザーが知ってることは異なり、互いにおぎない合ってる。我らは鍵の神、彼らは門の神。僕らのパワーをひとつに合わせれば……
このギャップをどう埋めるか?
メディア・クエリは災害対策の詰め合わせみたいなものだ。僕たちはブラウザーにこう話しかける。﹁なあ、僕はビューポートがどのくらいの大きさになるかわからないんだけど、でももしこのくらいの大きさなら、このファイルを使ってほしい。もしもっと大きければ、こっち。あと、こっちのやつは画面がレティナだった場合に使うけど、でもレイアウトが3カラムに切り替わったらそれじゃなくて……﹂。僕らは様々な可能性についてのラベルをファイルに貼っていく。そのラベルに書いてある内容は、ブラウザーは﹁知ってる﹂ことだけど、コードを書いてる僕らは﹁知らない﹂ことだ。
でもさっき見たとおり、実際にこれをやるのはとても骨が折れる。
じゃあ、もしこの状態をひっくり返したらどうだろう?
ブラウザーに対してごちゃごちゃした災害対策を提供するかわりに、シンプルにブラウザーが知らないことを教えてやったら? つまり、ビューポートに対する画像の相対的なサイズと、ソース・ファイルの寸法を。僕らはこのどちらも知ってる。もしこの知ってることをブラウザーと共有できたら、ブラウザーはソースを選ぶのに必要なことがすべて手に入ることになるんじゃない?
だよね! 実際、
<picture>仕様の最新にしてもっとも偉大なる草稿の、sizes属性と、srcsetの中のwディスクリプターは、まさにそのためにあるんだ。さっきの表をもう一度見てみよう。
| 変数 | 製作者が コードを書くとき | ブラウザーが ページを読み込むとき |
|---|---|---|
| ビューポートの寸法 | 知らない | 知ってる |
| ビューポートに対する画像の相対的な幅 | 知ってる | sizesがあれば! |
| 画面密度 | 知らない | 知ってる |
| ソース・ファイルの寸法 | 知ってる | srcsetがあれば! |
これを詳しく見る前に、確認しておきたいことが3つある。
まず第一に、これらを実装しているブラウザーはまだない。見通しは明るい2けど、仕様はまだ流動的だ︵画像のサイズが流動的なのといっしょ︶。だから使うのはちょっと待ってほしい。今はまだ動かないけど、もうすぐ使えるようになる。
ふたつめ。かつて、
忘れたかな? よし。
みっつめは、以前の
指定してるのは幅だけ、ってとこに注意。なんで高さも指定しないのかって? このレイアウトでの画像は幅で制御されてる。その幅はCSSで明示されてるけど、高さは指定されてない。実際のレスポンシブ画像のほとんども幅によって決まるので、仕様では幅だけを扱うことによってシンプルさを保とうとしてるんだ。
将来的には、ファイルの高さも
オーケー、これが
(一)少なくとも伸び縮みする画像の場合は。↩
(二)そして君も︵そう、そこの君も!︶この状況をもっと良くすることができる!↩
このコンテンツはSrcset and sizes — ericportis.com︵2014年3月24日公開︶の日本語訳です。本文中の各種技術仕様やその実装についての記述はオリジナル版公開時のものであり、現時点のものとは異なる場合があります。すべてのテキストとイラストレーションはクリエイティブ・コモンズ表示3.0ライセンスのもとに提供されています。
srcsetと呼ばれるレスポンシブ画像の提案があった。僕たちが話題にしている新しい提案も、同じくsrcsetと呼ばれる属性をもとにしている。古いsrcsetも新しいsrcsetも、カンマ区切りのURLのリストでwディスクリプターを使うけど、それぞれのwはまったく違う意味なんだ! 古いwはメディア・クエリのショートハンドで、ビューポートの幅をあらわしてた。一方、新しいwはファイルの幅をあらわす。僕らはこれから新しいwについて見ていくので、今のところは、﹃メン・イン・ブラック﹄の記憶消去装置みたいなやつを使って、srcsetとwについて知ってることをぜんぶ忘れてほしい。
忘れたかな? よし。
みっつめは、以前の<picture>仕様を期待を込めて追っかけてたひとへのお知らせ。新しい<picture>仕様でも、メディア・クエリによるソースの切り替えと、ソースURLでの解像度ディスクリプターは有効だ。もしアート・ディレクションしたり固定サイズの画像を解像度によって出し分けたりしてるなら、間違いなくこれらの機能を使うことになるだろう。でもシンプルに画像を伸び縮みさせるだけなら、ここで紹介する新しいツールが使える。
オーケー。これできれいさっぱり、準備が整った。さっきの例に戻って、今度はsrcsetとsizesを使ってみよう。
確認しとくと、僕たちが用意した画像には3つのバージョンがある。
●large.jpg︵1024 × 768︶
●medium.jpg︵640 × 480︶
●small.jpg︵320 × 240︶
そして36emのブレイクポイントでグリッドが1カラムから3カラムに切り替わる。
マークアップはこう。
<img src="small.jpg"
srcset="large.jpg 1024w,
medium.jpg 640w,
small.jpg 320w"
sizes="(min-width: 36em) 33.3vw,
100vw"
alt="A rad wolf" />
“picture”仕様をもとにしてるのに<picture>要素が見当たらない、って気づいたかもしれない。srcsetとsizes属性は<img>要素にも組み込むことができるんだ。この例のように、シンプルで、﹁アート・ディレクション﹂も﹁画像フォーマットの切り替え﹂もいらないようなとき、レスポンシブ画像のマークアップには僕らの古い友人である<img>が使えるし、そうしたほうがいい。
おなじみの<img>に、新しい属性。ひとつずつ見ていこう。
src="small.jpg"
おっと、これはちっとも新しくなかったね! このsrcはフォールバックで、srcsetとsizesを理解できないブラウザーでも、今までと同じように画像を読み込むためのものなんだ。次!
srcset="large.jpg 1024w,
medium.jpg 640w,
small.jpg 320w"
こいつもほとんど説明いらないよね。srcsetは、利用可能な画像のURLをカンマ区切りのリストで受け取る。それぞれの画像の幅はwディスクリプターで指定する。もし画像を1024 × 768で﹁ウェブ用に保存﹂したなら、その画像はsrcset内で1024wと指定すればいい。簡単。
指定してるのは幅だけ、ってとこに注意。なんで高さも指定しないのかって? このレイアウトでの画像は幅で制御されてる。その幅はCSSで明示されてるけど、高さは指定されてない。実際のレスポンシブ画像のほとんども幅によって決まるので、仕様では幅だけを扱うことによってシンプルさを保とうとしてるんだ。
将来的には、ファイルの高さもhディスクリプターで指定できたほうがいい理由がいくつか あるけど︵個人的にも、それは素晴らしいことだと思う︶、今のところはまだ。
そして注意しておきたいのは、srcsetの中のソースに、1x/2xといった解像度ディスクリプターをwディスクリプターのかわりに指定することもできるけど、1x/2xとwは混ぜて使わないこと。こいつらを同じsrcsetの中で使っちゃダメ。ゼッタイ。
オーケー、これがsrcsetとw。
あとブラウザーがソースを選ぶために必要なのは、レイアウトの中で画像がどんなサイズで描画されるかだけ。そのためにはsizesがある。さっきの例を見てみよう。
sizes="(min-width: 36em) 33.3vw,
100vw"
フォーマットはこう。
sizes="[メディア・クエリ] [長さ], [メディア・クエリ] [長さ] ..."
このようにメディア・クエリと長さを組み合わせる。ブラウザーは、マッチするものが見つかるまでメディア・クエリを見ていく。もし見つかれば、そのメディア・クエリとペアになった長さを、ソースを取ってくるパズルの最後のピース――描画される画像の幅、またはビューポートに対する相対的な幅として使う。
﹁なんだって?﹂と、君は言うかもしれない。﹁メディア・クエリ? メディア・クエリはまずいって言ってなかったっけ?﹂
僕が言ったのは、メディア・クエリをソースを選ぶメカニズムとして使うのはまずい、ってことなんだ。ここでやってるのはそれとは違う。ブラウザーがそのページのCSSで知ることになるブレイクポイントについて、ほんのちょっとだけ先回りして教えてあげてるんだ︵このほんのちょっとの時間がすごく重要!︶。最初の例では、レイアウトのたった1つのブレイクポイント︵36em︶のために、いくつものクエリが無駄になってたのを覚えてるかな? 60em、20em、10em――ってのがとっちらかってたよね! その点、sizesのブレイクポイントは、そのページのブレイクポイントをそのまま反映したものになるはず。そしてそれぞれのメディア・クエリに続く長さが、そのメディア・クエリがマッチしたときの画像の幅を指定するんだ。
というわけで、ブラウザーは必要な情報をすべて手に入れた。のろまで、なまけもので、間違ってばかりの僕ら人間がパート1でやるはめになったような計算は、あとはブラウザーやってくれる。その間に僕らは、くつろいでグリンピースを食べはじめられる。神の意図されたように。
さらに! メディア・クエリの例では1xと2xの画面しかカバーできなかったのを覚えてるかな? こっちのマークアップならどんなdevice-pixel-ratioでも対応できる。もうどの解像度をサポートするのが適当かと迷う必要はない。たとえ2016年に4.8625xのスマートウォッチが登場したとしても、srcsetとsizesならカバーできる。
まだある! この解決策はブラウザーに選択の幅をもたらす。ソースと結びついたメディア・クエリは真か偽かのいずれかの結果になり、もし真なら、ブラウザーはそのソースを読み込まなきゃいけない。でもsizesとsrcsetはそこまで頑固じゃない。仕様では、通信が遅かったり高くついたりするとき、小さいソースを読み込むオプションが認められている。
﹁どうやらすべてうまくいくように思えるね﹂と君は言い、ゆっくりとうなずきながら、条件分岐的アプローチよりも宣言的アプローチのほうに利点がある、と納得しはじめる。﹁でもちょっと待って……長さってなに?﹂
長さはあらゆる種類が考えられるよ! 絶対値︵99pxや16em︶でも相対値︵例に出てきた33.3vwとか︶でも。ただ実際のレイアウトでは、ここでの例とは違って、絶対値と相対値が組み合わされてることがたくさんあると思う。そこで、意外にもけっこうサポートされてる calc()関数の登場。例の3カラムのレイアウトに12emのサイドバーを追加するとしよう。それにはsizes属性をこう調整すればいい。
sizes="(min-width: 36em) calc(.333 * (100vw - 12em)),
100vw"
できあがり!
﹁わかったわかった﹂君は思慮深くそう言い、あごをさすりながら、新しい知識がどっと流れ込んできたことにひどく疲れて︵でも同時にわくわくして︶いる。﹁けれども、まだひとつ残ってる――そこにぶら下がってる100vwはなんだ? メディア・クエリを書き忘れたのか?﹂
仕様の言葉を借りて言うと、メディア・クエリとペアになっていない長さは﹁デフォルトの長さ﹂だ。もしマッチするメディア・クエリがなかったとき、この長さが使われる。つまり、巨大な、ページ全体にまたがる幅のバナー画像なら、マークアップはこんなふうにシンプルになる。
<img src="small.jpg"
srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w"
sizes="100vw"
alt="A rad wolf" />
カンタン、カンタン。
(一)少なくとも伸び縮みする画像の場合は。↩
(二)そして君も︵そう、そこの君も!︶この状況をもっと良くすることができる!↩
このコンテンツはSrcset and sizes — ericportis.com︵2014年3月24日公開︶の日本語訳です。本文中の各種技術仕様やその実装についての記述はオリジナル版公開時のものであり、現時点のものとは異なる場合があります。すべてのテキストとイラストレーションはクリエイティブ・コモンズ表示3.0ライセンスのもとに提供されています。
| 著者 | エリック・ポーティス(Eric Portis) |
|---|---|
| 訳者 | 鈴木丈(Takeru Suzuki) |
| 公開日 | |
| 更新履歴 | Commits · terkel/srcset-sizes · GitHub |