画面の大きさとピクセル比
このページは前もって作ってあって、 作っているところには画面がありません。 大きさもピクセル比もブラウザの中でしか分からないので、 この下の数は画面が出たあとに入ります。
- 画面全体screen.width × screen.height
- 測っています…
- 表示領域window.innerWidth × innerHeight
- 測っています…
- いま見えている範囲visualViewport・キーボードやピンチで変わる
- 測っています…
- ピクセル比devicePixelRatio
- 測っています…
- 画面の向きscreen.orientation
- 測っています…
- 色数screen.colorDepth
- 測っています…
- 画面の縦横比画面全体を約分したもの
- 測っています…
上の「画面全体」はCSSピクセルです。 端末の箱に書いてある数(物理ピクセル)とは別の数え方です。ピクセル比を掛けて、はじめて近い数になります。
- 幅
- 測っています…
- 高さ
- 測っています…
- 1つのCSSピクセルを描く粒の数
- 測っています…
これは推定です。ブラウザは物理ピクセルの数そのものを教えてくれません。 ピクセル比にはブラウザの拡大も混ざるので、 端末の仕様表に書いてある数とぴったり合わないことがあります。
窓の大きさを変えると、この数は変わります。パソコンなら窓の角をつまんで動かしてみてください。 スマートフォンなら横に倒すと入れ替わります。 窓の大きさ・画面の向き・ピクセル比のどれが変わっても、その場で測り直しています。 計算はぜんぶ、いま開いているブラウザの中だけで終わっています。
よくある質問
端末の仕様表に書いてある数と、このページの数が違います
仕様表に載っているのは物理ピクセル(画面の粒の数)で、ブラウザの screen.width が返すのはCSSピクセルです。別のものを数えているので、食い違います。CSSピクセルの数にピクセル比(devicePixelRatio)を掛けると、物理ピクセルに近い数になります。たとえば幅が390でピクセル比が3なら、390×3=1170です。
devicePixelRatio とは何ですか?
1つのCSSピクセルを、画面の粒いくつぶんで描いているかという比です。CSSOM View Module は「そのときのページの拡大率でのCSSピクセルの大きさを、端末のピクセルの縦の大きさで割った値」と定めています。比が2なら、たて2×よこ2の4個の粒で1つのCSSピクセルを描いています。
ページを拡大すると、ピクセル比は変わりますか?
ブラウザによって違います。仕様は「そのときのページの拡大率で」と書いているので変わるのが筋ですが、Safari は変えません。WebKit の課題124862でApple の開発者が「これは拡大していないときの一定の対応のつもりで作った」と説明しています。ですからこのページでは「拡大すれば変わります」とは書きません。ご自分のブラウザで拡大して、上の数が動くかどうか確かめてみてください。
screen.width と window.innerWidth は何が違うのですか?
screen.width は画面全体の幅、window.innerWidth はいまブラウザが中身を描いている領域の幅です。ブラウザの枠・タブ・アドレスバーのぶんだけ innerWidth のほうが小さくなります。仕様は innerWidth について「表示されているスクロールバーの大きさも含む」と書いているので、スクロールバーのぶんは引かれずに入っています。
visualViewport は何を測っているのですか?
指でつまんで拡大したときや、画面にキーボードが出てきたときに、実際に目に見えている範囲です。仕様はズームを2種類に分けていて、ページの拡大は表示領域そのものの大きさを変えるのに対し、visualViewport の倍率は虫めがねのように働いて表示領域の大きさを変えません。だから innerWidth は動かないのに visualViewport だけ変わる、ということが起きます。
色数が24ビットと出ますが、本当に測った数ですか?
測った数とは限りません。CSSOM View Module は colorDepth について、実際のビット数を返すべきだとしたうえで「分からないとき、またはプライバシーの都合で返したくないときは24を返すべき」と定めています。同じ仕様には、画面の情報は利用者のプライバシーを守るために隠してよい、という節もあります。24ビットは赤・緑・青が各8ビットで、256×256×256=16,777,216色です。
測った数はどこかに送られますか?
送っていません。このページは開いたブラウザの中だけで画面を測って、その場で計算して出しています。数はどこにも保存せず、どこにも送りません。窓の大きさを変えたときの測り直しも、同じくブラウザの中だけで終わっています。
いま開いている画面を、その場で測ります。CSSピクセルと物理ピクセルは別の数なので、 ピクセル比を掛ける式ごと並べます。
「解像度」で出てくる数と、ここの数が食い違うわけ
端末の箱や仕様表に載っているのは物理ピクセル、 つまり画面に並んでいる光る粒の数です。 いっぽうブラウザの screen.width が返すのはCSSピクセルで、 こちらは粒の数ではありません。 別のものを数えているので、一致しないのが正しいのです。
2つをつなぐのがdevicePixelRatio(ピクセル比)です。 CSSOM View Module は、この値の出し方をこう決めています ──「そのときのページの拡大率でのCSSピクセルの大きさを、端末のピクセルの縦の大きさで割る」。 割り算の答えなので、比が2なら「CSSピクセル1つは端末のピクセル2つぶんの背丈」という意味になります。
面白いのは、この定義がわざわざ「縦の大きさ」と言っているところです。 たてとよこで粒の並び方が違う画面がありうるので、 どちらで測るのかを決めておかないと値が定まりません。 仕様というのは、こういう「どちらでもよさそうなところ」を1つに決める仕事をしています。
CSSピクセルは長さの仲間ではなく、「見える角度」の単位です
ここがこのページで一番おもしろいところです。 CSS の絶対単位の一覧は、2つの組に分けて書かれています ──物理の単位(in・cm・mm・pt・pc・Q)と、視角の単位(px)です。px だけが、長さではなく「見える角度」の側に置かれているわけです。
もとになっているのが参照ピクセルという考え方で、仕様はこう書いています。「1インチあたり96個の粒が並ぶ画面を、腕の長さだけ離れて見たときの、 粒1つが見える角度」。 腕の長さを28インチ(約71センチメートル)とすると、その角度は約0.0213度になります。
角度で決めてあると、1px の実際の大きさは、見る距離で変わってよいことになります。 仕様自身がその例を出していて、腕の長さ(71センチメートル)で見るなら1pxは約0.26ミリメートル、 3.5メートル離れて見るなら約1.3ミリメートルだと書いています。 遠くから見る大きな案内板の文字が、近くで見ると驚くほど粗いのは、 このためだと考えると分かりやすいはずです。
96 という数が動かせなくなった経緯も、仕様に書いてあります
いまの CSS では1インチ=96px ちょうどと決まっていて、 cm も mm も pt もこの比で互いに固定されています。 ところが昔の CSS では、そうではありませんでした。 物理の単位は実際の長さに結びつき、 px のほうが参照ピクセルに合わせて伸び縮みしていたのです。
なぜ変えたのか。仕様はその理由を、めずらしくはっきり書いています ──「1インチ96個という前提に頼っている中身があまりに多く、それを崩すと壊れてしまうから」。そして自分でその変更を「不幸な変更」と呼んでいます。すでに広まってしまったものに、あとから規格のほうが合わせたという記録です。
ピクセル比が3の画面は、1つのCSSピクセルを9個の粒で描いています
ピクセル比はたて・よこの両方に効くので、1つのCSSピクセルを描くのに使う粒の数は、比の2乗になります。 比が2なら4個(たて2×よこ2)、比が3なら9個(たて3×よこ3)です。 上の四角い絵が、その分かれ方をそのまま描いたものです。
ここから、写真やイラストの重さが決まります。同じ大きさに見える絵でも、比が3の画面にきれいに出すには9倍の粒ぶんのデータが要ります。「高精細の画面用の画像は重い」と言われるのは、面積が2乗で効いてくるからです。
この数え方は思いつきではなく、CSS の仕様の説明図がまさに同じことを言っています。1px×1px の面積が、粗い画面では点1つで覆われ、細かい画面では16個の点で覆われるという図です。16は4の2乗で、ピクセル比4の画面の話になっています。
拡大したときに数が変わるかどうかは、ブラウザによって違います
ここは言い切ってはいけないところです。 仕様は「そのときのページの拡大率で」と書いているので、 ページを拡大すればピクセル比も変わるのが筋です。 実際そうなるブラウザがあります。
ところがSafari は変えません。 これは見落としではなく、考え方の違いです。 WebKit の課題124862で、Apple の開発者が2013年にこう書いています ──「Apple はこれを、拡大していない状態でのCSSピクセルと端末のピクセルの 『一定の』対応のつもりで作った」。 つまり同じ名前の値に、2通りの意味が乗っている状態です。
だからこのページは「拡大すると数が変わります」と書きません。お使いのブラウザで実際に拡大してみて、上のピクセル比が動くかどうかを見てください。動けば拡大を含めて数えるブラウザ、動かなければ含めないブラウザです。説明を読むより、自分の画面で確かめるほうが確かです。
3つの「大きさ」は、測っている場所がそれぞれ違います
screen は画面全体です。ブラウザの窓を小さくしても変わりません。window.innerWidth はブラウザが中身を描いている領域で、 枠・タブ・アドレスバーのぶんだけ小さくなります。 仕様は innerWidth について「表示されているスクロールバーの大きさも含む」と書いているので、 右端のスクロールバーのぶんは引かれずに入っています。
3つ目のvisualViewportだけが、少し性質の違うものを測っています。 仕様はズームを2種類に分けていて、ページの拡大は表示領域そのものの大きさを変えるのに対し、visualViewport の倍率は虫めがねのように働いて、表示領域の大きさを変えません。 指でつまんで拡大したときや、画面にキーボードが出てきたときに、ここだけが動きます。
色数の「24」は、測った数とは限りません
screen.colorDepth について、CSSOM View Module は実際のビット数を返すべきだとしたうえで、こう続けています ──「分からないとき、またはプライバシーの都合で返したくないときは24を返すべき」。同じ仕様には「画面の情報は、利用者のプライバシーを守るために隠してよい」という節もあります。
つまりこの欄は、測った値かもしれないし、決められた既定の値かもしれません。仕様にはさらに「32を返す実装が知られている」という注意まで付いています。数が出ているからといって、測った結果とは限らない── 画面まわりの値を扱うときに、覚えておくとよいところです。
なお24ビットというのは、赤・緑・青をそれぞれ8ビットで表す、という意味です。 8ビットは256段階なので、256×256×256=16,777,216色になります。
出どころ: 単位と参照ピクセルはW3C CSS Values and Units Module Level 3(絶対長さの節)(新しいタブで開きます)、画面まわりの値の定義はW3C CSSOM View Module(新しいタブで開きます)、ピクセル比の見張り方はMDN の devicePixelRatio(新しいタブで開きます)、Safari の考え方はWebKit の課題124862(新しいタブで開きます)から取っています。角度の0.0213度は、仕様の書いている96dpi と28インチから計算し直して、原典と同じ値になることを単体テストで確かめています。 測った数はどこにも送っていません。