HTML・CSS の viewport がよく分からなかったので、実験・調査した結果をまとめてみた。
モバイルとデスクトップで挙動が異なるので、その違いを中心に書いている。
本来は OS・ブラウザ・バージョンの組み合わせでも多少挙動が異なるが、今回はこの差異は考慮せず、MacBook Pro と iPhone XS に固定して検証した。
TL;DR
モバイル対応するには、モバイル向けの basic.css とデスクトップ向けの desktop.css を用意し、HTML の <head>
内で次のように書く。
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="css/basic.css" rel="stylesheet">
<link href="css/desktop.css" rel="stylesheet" media="(min-width: 600 px)">
または、CSS 内のメディアクエリで次のように書く。
/* モバイル向け CSS 記述 */
@media (min-width: 600 px) {
/* デスクトップ向け CSS 記述 */
}
検証環境
- MacBook Pro (15-inch, 2018) 10.14.4 (Mojave), Google Chrome
- iPhone XS (iOS 12.3), Google Chrome
ピクセル
- 物理ピクセル:ディスプレイの物理的なピクセル
- e.g., MacBook Pro (15-inch): 2,880 x 1,800
- e.g., iPhone XS: 2,436 x 1,125
- CSS ピクセル(論理ピクセル)
- 疑似解像度・スケーリング解像度
- n^2 個の物理ピクセルで 1 個の CSS ピクセルを構成
- e.g., 4 個の物理ピクセルで 1 個の CSS ピクセルを構成
- e.g., MacBook Pro (15-inch): 1,024 x 640 - 1,920 x 1,200
- e.g., iPhone XS: 812 x 375
- DPR (Device Pixel Ratio)
- 物理ピクセルと CSS ピクセルの比率
- e.g., 1 個の CSS ピクセルが 2^2 の物理ピクセルで構成される場合、DPR は 2
Viewport
モバイル | デスクトップ | |
---|---|---|
viewport のデフォルトの横幅 | 980 px | ブラウザの論理ピクセルの横幅 |
- viewport の横幅 = ページ全体の width: 100%
メディアクエリ
モバイル | デスクトップ | |
---|---|---|
width | viewport の横幅 | viewport の横幅 |
device-width(非推奨) | ディスプレイの論理ピクセルの横幅 | ディスプレイの論理ピクセルの横幅 |
JavaScript で取得できる横幅
モバイル | デスクトップ | |
---|---|---|
screen.width | ディスプレイの論理ピクセルの横幅 | ディスプレイの論理ピクセルの横幅 |
window.innerWidth | viewport の横幅(?) | viewport の横幅(スクロールバー含) |
document.documentElement.clientWidth | viewport の横幅 | viewport の横幅 - スクロールバーの横幅 |
- デスクトップの window.innerWidth の横幅はディスプレイ全体でなく、ブラウザが基準
- モバイルの window.innerWidth は viewport の横幅っぽいが、少し挙動が怪しい
一致するもの
- 共通
- ディスプレイの論理ピクセルの横幅 = device-width = screen.width
- モバイル
- viewport の横幅 = width = document.documentElement.clientWidth
- デスクトップ
- viewport の横幅 = width = window.innerWidth
<meta name="viewport" content=""> の content 属性の値
width
- 値:正の整数または文字列
device-width
- ウェブサイトを描画したいビューポートの幅をピクセル数で定義します。
- モバイルでのデフォルトは 980 px
initial-scale
- 値:
0.0
から10.0
までの、正の数値- デバイスの幅 (ポートレートモードでの
device-width
またはランドスケープモードでのdevice-height
) とビューポートの寸法との比率を定義します。
- device-width / initial-scale = width
- e.g.,
initial-scale=0.5
の場合、iPhone XS(device-width: 375 px)の(viewport の)width は
375 px / 0.5 = 750 px
- e.g.,
-
initial-scale=1.0
の場合、width = device-width
- e.g.,
<meta name="viewport" content="initial-scale=1.0">
- e.g.,
maximum-scale
0.0
から10.0
までの、正の数値- ズームの最大値を定義します。この値は
minimum-scale
と同じまたはより大きくしなければなりません。そうではないときの動作は未定義です。ブラウザーの設定でこの規則を無視できます。また、iOS 10 以降は既定で無視します。
- device-width / maximum-scale の横幅までズームイン可能
- e.g.,
maximum-scale=2.0
の場合、iPhone XS(device-width: 375 px)では、375 px / 2.0 = 188 px
より、横幅 188 px までズームイン可能-
maximum-scale=1.0
:横幅 375 px まで(devie-width 以上にズーム不可) -
maximum-scale=0.5
:横幅 750 px まで
-
minimum-scale
0.0
から10.0
までの、正の数値- ズームの最小値を定義します。この値は
maximum-scale
と同じまたはより小さくしなければなりません。そうではないときの動作は未定義です。ブラウザーの設定でこの規則を無視できます。また、iOS 10 以降は既定で無視します。
検証
検証に用いた HTML・CSS・JavaScript のソースコードとその表示結果を貼っておきます。
感想
かなりややこしい。モバイルでの viewport の横幅がデフォルトで 980 px なのが諸悪の根源な気がする。普通に device-width の値がデフォルトでは駄目なのだろうか。
今後の課題
-
CSS の @viewport の調査← deprecated になっていました - モバイルのポートレートモード(縦長)とランドスケープモード(横長)での挙動の調査
参考
- Peter Gasston(2015)『CSS3開発者ガイド 第2版』牧野聡訳,オライリー・ジャパン,https://www.oreilly.co.jp/books/9784873117256/.
- <meta>: 文書レベルメタデータ要素 - HTML: HyperText Markup Language | MDN
- device-width - CSS: カスケーディングスタイルシート | MDN
- Configuring the Viewport
- A pixel is not a pixel is not a pixel - QuirksBlog
- モバイルブラウザでのレイアウトを制御するために meta タグの viewport を使う - Mobile | MDN