viewport、ちゃんと理解できておりますでしょうか。
それには歴史的経緯やスマホにおけるブラウザの実装などを追う必要があり、たくさんの記事を読むというしんどい過程を迫られることと思います。
この記事は、そうしたネットに転がる情報をまとめ、これひとつ読むだけで 「あ~なるほどね、だいたい理解した」となれる道しるべ的なものとして書きました。2020年にしては少し古すぎる話かもしれませんがご了承ください。
なお、ぼく自身はフロント歴がほぼ0のぺーぺーです。RFCとか各ブラウザの実装、最近のドラフトではこうだよ~とかあればご教示いただけると幸いです。
viewportを理解する
viewportはモバイル端末で使われる レイアウトを計算するときの仮の領域1です。
これでほとんど説明はおしまいなのですが、この記事ではさらに
- 歴史的経緯
- 現在の状況
meta
タグでの実践- 表示上のピクセル、デバイス上のピクセル
を通して理解を深めたいと思います。
viewportはどういうものだったのか?
viewportの考案以前、モバイル端末の画面は横幅360pxほどなのに対し、たいていのWebページはPCのモニタの横幅1024pxをベースに考えられていました 2。このままだとほとんどのページはスマホの画面をはみだしてしまいます。そこで、 一旦横幅980px 3の仮想的な画面としてレイアウトを計算し、それをデバイスの実際の横幅に合わせて縮小することで、どんなページでもスマホの画面に収めて表示できるようにしました。
この仮想的な横幅980pxの領域こそviewportであり、こうした動作が基本的なviewportの挙動になります。
現代のviewport
とはいえ、現代ではスマホをまったく想定していないサイトも珍しいですし、それでなくともviewportのデフォルトの挙動がお世辞にもいいとは言えません。
そこで「レイアウトを計算するときの仮の横幅」に自然な値を指定しつつ、しかるべきモバイル対応をしたスタイルをメディアクエリなどを駆使して当てていくことが求められるようになってきました。
metaタグで指定できるviewport
さて、「レイアウトを計算するときの仮の横幅」を指定するのに使うのが、今日よく目にする以下の meta
タグの正体です。
<metaname="viewport"content="width=device-width, initial-scale=1">
これは、
- レイアウト計算時の横幅にデバイスの横幅(CSS Pixel)を指定
- この幅を1倍の拡大率として扱う
という意味になります。
無指定の場合は980px・1倍扱いです 4。
たとえば、横幅640px(CSS Pixel)のスマホで先の meta
タグを設定すると、Webページ側では横幅は 100%
= 100vw
= 640px
で認識されます。ここでviewportの幅に320pxを指定すると、Webページ側では横幅320px扱いで計算されたのち、横幅640pxにフィットするように拡大・縮小されて表示されます(拡大・縮小後もWebページ側では320px扱いのまま)。
ちなみに、この meta
タグには他にも拡大・縮小に関する設定ができます。指定できる設定項目は MDNを参照してください。
CSS Pixel, Device Pixel
なお、 device-width
の横幅も、実際のデバイスが持つ画素数とは異なります。
つまり、実際にはさらに拡大・縮小的な処理がなされることになります。
この device-width
の横幅を表す仮想的なピクセルをCSS Pixel、実際のデバイスの画面を構成しているピクセルをDevice Pixelと呼びます 5。
このような区分は、Retinaとか4Kでの表示の仕方と近いものがあります。
この図を見てください(プリンターとは事情が異なりますが、あくまでDPIの例として)。
左側はグリッドで区切られた領域内にひとつずつのドットがありますが、右側は領域内にさらに細かいドットを使って表現しています。
しかしいずれも 画像の上では同じ大きさですよね。
これがもし、右側の細かいドットを使って左側と同等の絵を描いたら、1/4くらいの大きさになって見づらくなってしまいます。
こういう、 表示物を現実での大きさでいい感じにする処理が高DPI環境では行われています。そして、この最終的な見え方としての解像度とデバイスが持つ物理的な解像度とを扱うために、CSS PixelとDevice Pixelという要素が登場することになります。
実用上の理解としては、DPIの違いがあってもブラウザやOSがよしなにやって同じくらいの見え方に調整してくれる、と覚えておいていいでしょう。
つまりviewportとはどういうものか
まとめると、このような図になります。
あなた(とそのコードを読んだブラウザ)はviewportに対してレイアウトをし、そのレイアウトはブラウザによって拡縮されて表示されます。
実装の上では、以下のようにviewportを理解して付き合っていくとよいように思います。
- モバイル向けブラウザは仮想的な解像度を作って拡大・縮小の処理をする
<meta name="viewport" content="width=device-width, initial-scale=1">
を使うと、本当は小さい画面でも980pxで扱われることなく、表示領域の大きさをそのまま受け取ることが出来る- 逆に使わないと、モバイル環境では横幅が980pxの扱いになり想定外の挙動をするかも
本当は縦幅も含めた概念ですが、実装しているブラウザはないため本記事ではほとんど横幅の話しかしません。 ↩
Using the viewport meta tag to control layout on mobile browsers - Mozilla | MDN ↩
非モバイル端末(パソコンとか)ではviewportの指定は無視されますが、だからといって無指定同様の挙動をするわけではありません。ウィンドウサイズと同等の値がviewport扱いの挙動となるようです。 ↩