viewport の理解が難しいのは viewport が実は多義語だから説
<meta name="viewport">
で言ってる viewport って結局なんなんだって話です。
viewport の解説記事は世に数あれど、どれを読んでもすぐに理解が揮発してしまう病に悩まされていたのですが、最近になってその原因が viewport の多義性にあったんじゃないかと思い当たりました。実は多義語である viewport に関する色々な言及を方々で目にするうちに、viewport って結局なんだったんだっけ……?になりがちなんじゃないかと。
そこで本稿では異なる意味の viewport をきちんと呼び分けながら <meta name="viewport">
の典型的な挙動を再確認することを試みます。
viewport とは
さて、巷では viewport という語は少なくとも次の 4 つの意味で使われているようです:
- layout viewport の略称
- visual viewport の略称
- https://www.quirksmode.org/mobile/metaviewport/ が言うところの ideal viewport。つまり、
initial-scale=1
の下でのページロード直後の visual viewport。 - (2, 3 から派生して?) モバイル端末の物理的な画面領域のこと (参考)
<meta name="viewport">
が言う viewport はまさに layout viewport のことですが、<meta name="viewport">
の設定がブラウザ*1のレンダリングにどう影響するのかを語るためには layout viewport と visual viewport (と、本当は ideal viewport) に触れなければなりません。
<meta name="viewport">
とレンダリング
以下、initial-scale=1
を仮定します。通常 initial-scale
は 1 であるべき*2ですし、1 以外のケースを想定すると話がとてもややこしくなるので。また、ページロード直後についてのみ考えます。言い換えると、ズームについて考慮しません。理由は同上。 <meta name="viewport">
を自身で設定するに際しての理解としては、この仮定の下でも問題ないはずです。
まず、html, CSS, JS は layout viewport をこの宇宙の大きさだと思って動き、layout viewport に文書を"レンダリング"します。もちろんこれは比喩ですが、つまり例えば <meta name="viewport" content="width=300">
によって layout viewport の width を 300px と定めたならば、CSS での 100vw は 300px を意味しますし、media query から見た screen width はいつでも 300px ですし、 JS の window.innerWidth の値も 300 です*3 。
次に、そうして"レンダリング"を終えた layout viewport を実際にブラウザの表示領域、すなわち visual viewport に"投影"します。visual viewport は端末と環境に固有の大きさ*4*5を持ちます。もし layout viewport と visual viewport の大きさが異なるならば、”投影”時にブラウザは layout viewport を拡大縮小して visual viewport の大きさに近づけようとします*6。
device-width, device-height
ところで、<meta name="viewport">
の中ではdevice-width, device-height というキーワードが有効ですが、これがまさに visual viewport の大きさ*7です。
width=device-width
を設定すると visual viewport と layout viewport の幅が一致するので、投影時の拡大縮小が発生しませんし、media query は端末ごとに異なる値を受け取れるのでレスポンシブに設計されているサイトではその恩恵に預れます。
デモ
本稿の執筆にあたってブラウザの実際の挙動を確認するためにデモを書いたので参考までに。
https://github.com/penpenpng/viewport-demo
雑感
- viewport が多義語だから~とかじゃなくって、やっぱ viewport がそもそもムズい。どうにか簡単にまとめようとしたら仮定まみれになってしまった。
- 世の記事を読んでも理解が揮発するのは、そもそもムズい viewport をなんとか簡単に説明するために細かいところをぼんやりとごまかしているから。
- viewport まわりの話の中で出てくる長さの単位はすべて CSS Pixel だということを強く意識しておくとより理解しやすくなるなとも感じた。気が向けば CSS Pixel の話も書くかも。
参考
- https://developer.mozilla.org/en-US/docs/Glossary/Visual_Viewport
- https://developer.mozilla.org/en-US/docs/Glossary/Layout_viewport
- https://developer.mozilla.org/ja/docs/Web/CSS/Viewport_concepts
- https://developer.mozilla.org/ja/docs/Web/HTML/Viewport_meta_tag
- https://design-spice.com/2012/09/05/resolutio/
- https://qiita.com/ryounagaoka/items/045b2808a5ed43f96607
特に、以下がとても詳しいです:
*1:以後断りのない限りモバイルブラウザを指します。PC ブラウザは原則として meta タグによる viewport の設定を反映することはありません。
*2:個人の意見。そうでない場合があったら教えてください。
*3:width に設定した値が極端に小さかったり大きかったりする場合はこの限りではないようで、環境依存の値でクリップされることがあります。が、わざわざそんな値を設定することはおそらくないと信じて本稿では無視して話を進めます。
*4:厳密に言えば、端末と環境に固有の大きさを持っているのは ideal viewport の方で、visual viewport のサイズはユーザのズーム操作によって変化します。ズームすると CSS pixel の大きさが変化するからです。しかし本稿の仮定のもとでは visual viewport は固定値です。
*5:ideal viewport は iPad の Split View で表示されている場合などには変化し得ます。
*6:MDN などによると layout viewport と visual viewport の width が一致するように layout viewport を拡大縮小するそうですが、実際に実験してみると必ずしもそうではないようだったので表現を濁しています。追記: quirksmode によるとどのように拡大縮小されるかは環境に依存するようです。
*7:本稿の仮定の下で。