最近はレスポンシブデザインというものと日々戦いを繰り返し、ジャングルの密林で銃撃され続け、疲弊し、厭戦気分が高まりつづけた結果としてヒッピー化している今日このごろなのですが、フロントエンド開発というかレスポンシブデザインというか、そういう文脈において、いわゆる高精細ディスプレイだとか、viewport がどういう役割を果たすのかがなかなか具体的に分からなかったので、そのあたりのお話です。
ブレイクポイント
説明を単純にするために敢えて話を単純化すると、レスポンシブデザインでは、画面の横幅によって CSS を切り替え、結果としてページデザインが切り替わるようになっています。この切り替えポイントを、ブレイクポイントと呼びます。 ブレイクポイントを指定する単位はいくつかあるのですが、まぁ多くの場合はピクセル (px) を使用するみたいですね。
ここで問題になるのが高精細ディスプレイです。iPhone 4 から搭載された Retina Display とか、Android にも高精細ディスプレイという触れ込みで搭載されていたりします。高精細ディスプレイって、ピクセルの考え方が 2 つあるんですよね。。。
CSS Pixel と Device Pixel、そしてデバイス・ピクセル比
Retina だったりに代表される高精細なディスプレイは、通常の 1 ピクセル (いわゆる CSS Pixel; CSS で扱う論理的なピクセル) を物理的なデバイス上の複数のピクセル (Device Pixel) で表示しています。 この、CSS Pixel と Device Pixel の比を device pixel ratio と呼びます。高精細ディスプレイでは、この device pixel ratio が 1 より大きくなるってことですね。
Density-independent pixel (dp)
で、全部が全部、このデバイス・ピクセル比で表現されると良いんですけど、Android では dp
という単位を元に、別に定義しています。
この dp
っていうのは、このページで、160 dpi のスクリーン上でのデバイスピクセル値の単位として定義されてます。この dp
の値を使用すると、任意の端末上のピクセル値は、px = dp * (dpi / 160)
として計算することができます。
個々の端末の dp の値なんかは こちらのページにまとまっているので参考にできそうですね。
viewport
で、viewport の話です。 よく、フロントエンドでスマフォ対応しようとすると、以下のような meta タグを書くと思いますが、この viewport っていうのが何なのかが分からなかったので調べてみました。
<meta name="viewport" content="width=device-width,initial-scale=1">
スマートデバイスについて話をすると、この viewport の概念というのは次の 2 つに分かれます。
- layout viewport
- visual viewport
下の図が分かりやすいんですが、layout viewport っていうのは言ってみればレンダリング用の仮想的な矩形です。この矩形上に html の記述内容がレンダリングされます。 一方、visual viewport というのが、実際の画面上で表示される範囲です。ズームしたりスワイプしたりすると visual viewport は変化しますが、layout viewport のサイズっていうのは変わりません。
上記の meta タグで指定している width というのは、layout viewport に対する横幅の指定になります。 ブラウザによってデフォルト値は違いますが、iPhone では 980 px らしいですね。なので、meta タグで指定しない限り、こんなかんじで、横幅 980 px で表示した場合の PC 画面用レイアウトがそのまま表示される形になります。
ちゃんと meta タグで layout viewport の横幅を指定してやると、ちゃんとモバイルで見えやすいように表示されるってわけですね。