いまさら聞けないRetina対応のための「ピクセル」の話

個人的には高解像度ディスプレイへの対応より、表示パフォーマンスのほうが大切だと考えているので、あまり積極的に高解像度ディスプレイへの対応について考えてきませんでした。ところが、最近発売される端末を見ていると、ほとんどの端末が高解像度で、通常の3倍サイズの画像が必要になるCSSピクセル比が3倍なんていう端末も出てきています。先日のSVGに関する記事もその流れから書いたもので、その記事にコメントいただいていた通り、高解像度端末が普通の時代が「近い将来」ではなく「今でしょ!」になっています。

たとえば、レスポンシブWebデザインで様々な画面サイズに対応したウェブサイトを作っても、高解像度端末では画像がボヤけたものばかりになってしまい、ユーザー体験に悪影響を及ぼす可能性も出てきます。競争が激しい昨今、特にイメージを重視するビジネスでは、ウェブサイトでもクリアな画像で鮮明なイメージを印象づけておくことは必須になります。※それでもページの表示スピードのほうが重要だと思いますがw

ということで、今回も高解像度ディスプレイ対応関連の内容ですが、SVGに続き今回はRetina対応に必要な「ピクセル」関連の基本情報についてまとめてみました。まずは、2種類のピクセルの定義から。次に、メディアクエリでの高解像度ディスプレイ対応についてまとめていきます。

注) この記事で書いている内容はウェブサイトの制作を念頭に置いています。アプリ制作に関する情報とは若干違ってくる可能性があるのでご注意を!

2種類のピクセル

デバイス・ピクセル(ハードウェア・ピクセル)

device pixel / hardware pixel

デバイス・端末がサポートする物理的な最小単位のピクセル。ハードウェア・ピクセルともいう。デバイス・ピクセルのほうが一般的に使われているようなので、この記事では統一してデバイス・ピクセルを使います。

CSSピクセル

css pixel / reference pixel

CSSで使う論理上のピクセル。デバイス・ピクセルが物理的なピクセルの数であるのに対し、CSSピクセルは論理上のピクセルの数です。デバイス・ピクセルとCSSピクセルの数が同じだったころは問題はありませんでした。しかし、Retinaディスプレイの登場で、それらが違う数になったため、デバイス・ピクセルとCSSピクセルを明確に分けて考える必要が出てきました。

例) iPhone 4のデバイス・ピクセルとCSSピクセルの違い

たとえばiPhone 4のスクリーンの物理的なピクセル数であるデバイス・ピクセルは640 x 960pxですが、論理上のピクセル数であるCSSピクセルは320 x 480pxになります。そのため、iPhone 4の場合、1つのCSSピクセルを4つのデバイス・ピクセルを使って表現しています。

ピクセル関連のその他の単位について

デバイス・ピクセル比(device pixel ratio)とは?

上で説明したデバイス・ピクセルとCSSピクセルの比率のことです。この比率が1:1、2:1、3:1の場合を図で表すと以下のようになります。たとえばiPhone 4の場合は真ん中の2:1になります。

デバイス・ピクセル比が 1:1 の場合、一番左の図のように、1つのCSSピクセルが1つのデバイス・ピクセルで表現されます。2:1の場合、1つのCSSピクセルが4つのデバイス・ピクセル、また、3:1の場合は9つ(3 x 3)のデバイス・ピクセルを使ってディスプレイに描画されます。

ピクセル密度(pixel density)とは?

1インチの中にあるピクセルの数(立方計算ではない)= ppi (pixels per inch)。dpi (dots per inch)も一般的に使われていて、これらは同じ意味で使われている場合が多いようです。たとえば、最近の端末のピクセル密度は以下のようになっています。

端末 デバイス・ピクセル(px) ピクセル密度(ppi) ピクセル比
iPhone 5 640 x 1136 326 2
Galaxy S IV 1080 x 1920 441 2
HTC One 1080 x 1920 468 3
Xperia Z 1080 x 1920 443 3

ピクセル密度とピクセル比の関係

ピクセル密度は、数が多ければ多いほどスクリーン上で鮮明な描画ができるわけですが、上述したピクセル比とは直接関連しないものです(と考えています)。たとえば、Galaxy S IVのようにピクセル密度は441ppi、ピクセル比は2という端末もあれば、HTC Oneのように、ピクセル密度は468ppiだが、ピクセル比は3という端末もあります。

※両方とも実機で検証したわけではないので、Wikipediaの情報が正しければの話ですが。
※ピクセル比とは違うものですが、それと似た単位であるdppx (dots per pixel unit)では、CSSで定義された1インチが96pxになるため、1dppx = 96dpiになります。

ピクセル比に似た値「dp」とwindow.devicePixelRatio

Androidの密度非依存ピクセル「dp」

Density-independent Pixel / dipともいう

このdpという単位は、Androidアプリを作る際に使われる単位で、Androidの開発者向けウェブサイトではDevice-independent Pixel(密度非依存ピクセル)という単位を定義しています。これは160dpiのピクセル密度を持つディスプレイで表示される1pxを1dpとしたもので、たとえば、320dpiの場合1px = 2dp1dp = 2px(2013/10/27修正)に、480dpiの場合3dp1dp = 3px(2013/10/27修正)になります。

この単位と上述のデバイス・ピクセル比は違うものなので注意が必要です。

window.devicePixelRatioについて

それぞれの端末のピクセル比が掲載されているウェブサイトは上述したWikipediaのページか、こちらのブログ記事しか見つけられませんでした。ピクセル密度は書いてあるんですが、ピクセル比は端末のスペックなどには書いてない仕様なんですね。そこで登場するのがwindow.devicePixelRatioです。

端末のピクセル比はwindow.devicePixelRatioを使うことで端末から取得することができます。たとえば、以下のようにJavaScriptを使ってピクセル比を表示させると僕のiPhone 5や同僚のGalaxy Nexusでは「2」と表示されました。ちなみに、QuirksModeさんが、こんな便利なテストページを作ってくれています。

<script>
document.write(window.devicePixelRatio);
</script>

window.devicePixelRatioの注意点

ところが、このwindow.devicePixelRatioを使う際は以下の2つに注意が必要です。

  1. FirefoxやIEでサポートされていない
  2. 同じ端末でもブラウザによって違う値を返す

QuirksModeのこの記事によると、たとえば、ディスプレイ・サイズが720 x 1200pxのGalaxy Nexusでは、AndroidブラウザやChromeでは2になるのが、Operaでは2.25になるそうです。これは、AndroidやChromeでは360pxをCSSピクセルにして計算しているのに対して、Operaでは320pxで計算しているからだそうです。

Androidブラウザの場合
720 ÷ 360 = 2

Operaの場合
720 ÷ 320 = 2.25

また、iPhone 5のSafari、Chrome、Operaで試してみたんですが、それぞれ、2、2、1が返されました。なぜかOperaだけ1でした。なぜ???これは謎です。

※Android端末では2.0以上でサポートされています。
※devicePixelRatioについてはこちらこちらのQuirksModeさんの記事(英語)が参考になります。

高解像度ディスプレイ対応に使うメディアクエリについて

高解像度ディスプレイ向けにクリアな画像を表示させる方法の1つに、メディアクエリの-webkit-device-pixel-ratioという特性を使用する方法があります。まずは-webkit-device-pixel-ratioについて。それから、メディアクエリのresolution特性について。そして、最後に高解像度向けのメディアクエリの記述についてまとめてみます。

-webkit-device-pixel-ratioについて

このdevice pixel ratioというのは、そもそもAppleがRetinaディスプレイを開発した際に、上記のデバイス・ピクセルとCSSピクセルの扱いを調整するために独自に作ったメディアクエリの特性で、それにAndroidが追随してサポートされるようになったものです。「Safari Developer Library」でのメディアクエリの説明を見ると、以下のように定義されています。

[引用]
-webkit-device-pixel-ratio
Applies only to devices with the specified ratio where a value of 2 indicates Retina displays and 1 indicates standard displays.
Available in Safari 4.0 and later.

[意訳]
デバイスが示す比率にのみ適用するプロパティ。「2」がRetinaディスプレイ、「1」が標準ディスプレイを示す。Safari 4.0以上で使える。

ここではなんの比率なのかは詳細には説明されていません。1が標準ディスプレイで、2がRetinaディスプレイと言っているだけです。しかし、iPhone 4はこのdevice-pixel-ratioが2になっていて、デバイス・ピクセルとCSSピクセルの比率が2倍(640 ÷ 320px)に相当するため、device-pixel-ratio = device pixel ÷ css pixelというふうに考えられます(そうじゃない可能性もありますが、仕様を決めた人に聞かないとわからないですね…)。

Androidでの-webkit-device-pixel-ratio

Androidの場合は、開発者向けのウェブサイトで以下のように説明がされています。

[引用]
The Android Browser and WebView support a CSS media feature that allows you to create styles for specific screen densities—the -webkit-device-pixel-ratio CSS media feature. The value you apply to this feature should be either “0.75”, “1”, or “1.5”, to indicate that the styles are for devices with low density, medium density, or high density screens, respectively.

意訳
AndroidブラウザとWebViewはある特定のスクリーン密度によってスタイルを作ることができるCSSメディア特性の-webkit-device-pixel-ratioをサポートしています。この特性に指定する値は「0.75」「1」「1.5」で、それぞれ「low density」「medium density」「high density」のスクリーンを示します。

この説明だと、ピクセル比とピクセル密度が関連しているように書かれているのですが、これがすごく曖昧で混乱を招いているように思います。ピクセル比はあくまでCSSピクセルとデバイス・ピクセルの比率なので、ピクセル密度とは関係がないはずです。

余談

ちなみに、「low density」「medium density」「high density」の定義は、開発者向けウェブサイトのアプリ向けの情報に書かれています。

resolutionについて

resolution特性は、昨年6月に正式にW3Cから勧告されたメディアクエリの仕様にも記載されているもので、W3Cウェブサイトでは以下のように定義されています。

The ‘resolution’ media feature describes the resolution of the output device, i.e. the density of the pixels. When querying devices with non-square pixels, in ‘min-resolution’ queries the least-dense dimension must be compared to the specified value and in ‘max-resolution’ queries the most-dense dimensions must be compared instead. A ‘resolution’ (without a “min-” or “max-” prefix) query never matches a device with non-square pixels.

ミツエーリンクスさんの訳
媒体特性 ‘resolution’ は、ピクセル密度など、出力デバイスの解像度を表す。非正方ピクセルなデバイスにおいて、‘min-resolution’ クエリーはデバイスの最低密度と指定された値を、また ‘max-resolution’ クエリーはデバイスの最高密度と指定された値を比べる必要がある。”min-” や “max-” 接頭辞のつかないただの ‘resolution’ クエリーは、非正方ピクセルなデバイスにおいて適合することはない。

resolutionで使える単位について

このresolutionで使える単位は、メディアクエリの仕様ページではdpiとdpcmと記載されているのですが、現在、2012年8月に勧告候補になっているW3CのCSS3の値のスペックでは、dppxという単位が追加されていて、その単位が一番わかりやすく、使える単位になるだろうと思っています。ちなみに、このdppxという単位をサポートするブラウザはまだないそうFirefox 16以上のみのよう [修正: 2013/4/4 21:27]です。

  1. dpi (dots per inch = 1インチにおけるドットの数)
  2. dpcm (dots per centimeter = 1センチにおけるドットの数)
  3. dppx (dots per ‘px’ unit = 1px単位におけるドットの数) ※勧告候補で、まだサポートしているブラウザが少ない [修正: 2013/4/4 21:31]

メディアクエリのresolution特性のdppx(dots per pixel unit)という単位は、CSSでは1インチ = 96ピクセルと定義されているので、1dppx = 96dpiとなり、ピクセル比とピクセル密度が関連する形になっています。ややこしい…

高解像度向けのメディアクエリの書き方

たとえば、デバイス・ピクセル比が2以上の端末向けに、高解像度向けのスタイルを指定する場合、以下のような記述になります。

@media screen and (-webkit-min-device-pixel-ratio: 2){
  /* 高解像度向けのスタイル
}

Firefox 16以下では-webkit-device-pixel-ratioがサポートされていなくて、-moz-device-pixel-ratioを使う必要があるのですが、Firefox16以下を使っているユーザの割合を見て、必要であれば使えばよいかと思います。

また、ベンダープレフィックスを使わない、将来的にも有効なメディアクエリの指定方法として、W3CのCSS WG Blogでは以下の記述方法を勧めています。

@media
(-webkit-min-device-pixel-ratio: 1.5),
(min-resolution: 1.5dppx)
{
  /* 高解像度向けのスタイル
}

dppxは古いブラウザでの実装ではCSS解像度を使わずにデバイス解像度を使っている場合があり、-webkit-device-pixel-ratioの2とは違った値になってしまう場合もあるそうです。また、dppxをサポートするブラウザでは問題なく実装されるので、将来性を見越してこちらを使うのは問題ないだろうとのことです(ほんとか?)。

古いブラウザも考慮したいというのであれば、CSS-Tricksで取り上げられていたような書き方もありだと思いますが、ベンダープレフィックスが沢山あって、ちょっと助長冗長 [修正: 2013/4/5 12:19] な気がするので、上記の記述で良いと思います。

まとめ

や、やっとまとまった…。

非常にややこしい情報で、調べれば調べるほど混乱してしまいました。この記事で、どうにかまとまったと思うんですが、読んだ方を一層混乱させないことを願うばかりです。汗

ただ、この記事の冒頭でも述べたように、すでに高解像度ディスプレイへの対応が必要になっています。この辺りの情報をしっかり理解しておかないと、今後わけがわからずにコードを書いたり画像をつくったりすることになると思うので、ちょっといまさらな感じもありますが、まだの方は自分なりに一度しっかり理解を深めておくと良いと思います。

しつこいようですが、表示パフォーマンスのほうを優先するべきだと考えているので、表示パフォーマンスをしっかり考慮したうえで、今後ますます密度が上がる高解像度ディスプレイにも対応できるように、CSS3やアイコンフォント、また、先日の記事に書いたSVGなどを活用した制作を進めるべきですね。

覚えることややることは増えるばかりですが、頑張りましょ〜!

参考にしたサイト

Androidアプリ制作関連

“いまさら聞けないRetina対応のための「ピクセル」の話” への5件のフィードバック

  1. […] いまさら聞けないRetina対応のための「ピクセル」の話 […]

  2. […] ググると色々出てきますが、とても良く整理されていて良いなぁと思ったサイトをひとつ紹介します。いまさら聞けないRetina対応のための「ピクセル」の話。 […]

  3. […] と思ったら最近はめんどくさいことになって来ているようです。さすがにこれはちょっと理解できませんでした。 http://parashuto.com/rriver/development/pixel-related-info-for-coping-with-retina-displays […]

  4. […] いまさら聞けないRetina対応のための「ピクセル」の話 […]

コメントを残す