意図せずに出てしまった小数点以下のピクセル(以下サブピクセル)で表示ミスしてしまったので、2014/06/05時点での私が用意できる最新ブラウザ※におけるレンダリングされ方についてまとめてみました。
※Chrome(35.0.1916.114), Firefox(29.0.1), Opera(22.0.1471.50),Safari(7.0.4(9537.76.4)),IE(11.0.9600.17031), mobile safari(7.0),Android Chrome(34.0.1847.114), Androidブラウザ(4.2.2-FJLjpkdi.20131219.1833),Chrome,Firefox,OperaはOSX上のもの、IEは仮想環境(modernIE)上のものです。
※2014-06-06 15:20 FirefoxにおけるRetinaディスプレイ時のレンダリングについて追記と修正しました
子要素の幅の合計が親要素の幅と一致する場合
例えば、あるボックスのなかに4つのボックスを均等に並べたいときは下記のように、子要素の幅の合計が100%になるようにwidthを指定するかと思います。
この場合.wrap
のwidth
値が4で割り切れる値であればいいのですが、例えば50pxなどの割り切れない値が出る場合、子要素のwidth
は12.5pxとサブピクセルの値となってしまいます。この場合に、各ブラウザによって挙動が異なりレイアウトが崩れてしまったり、意図しない隙間が出来てしまいます。
Chrome, Firefox, Opera, IEの挙動
今日時点で上記のブラウザの最新版は同じ挙動を示します。例えば、Chromeでは下の図のように赤い背景の親要素に隙間なく青い背景の子要素が収まってレンダリングされます。
上記のブラウザは、いずれもサブピクセルレンダリングに対応しているため、いい感じに埋めてくれるのですが、上記以外のブラウザについてはそうではありませんでした。
Safari(OS X&iOS),Androidブラウザの挙動 + IE7の挙動
いずれもWebkitをレンダリングエンジンに採用しているブラウザですが、上記の3つのブラウザは共通して下記のような挙動を示します。今回はSafari(OSX)の例です。
これらのブラウザでは、12.5pxの小数点以下を切り捨ててしまうため、12px * 4 = 48px
となり、結果右端に2pxの隙間が生まれ親要素の赤が見えてしまいます。この問題についてはjQueryを用いてゴリゴリ解決する方法もあるようです。Fixing Subpixel Layout Rendering in Safari
なお参考までにIE7以下では、四捨五入で繰り上げてレンダリングするため、今回のケースでは一番右の子要素がカラム落ちしてしまいます。
小数点以下の数値が親要素に満たないかはみ出した場合
先の章では、合計が100%であるが表示上100%にならない場合をとりあげましたが今度は、例えば幅が50pxのボックスの中に49.5pxや50.5pxの幅を持ったボックスがある場合はどうなるでしょうか。
Safari(OS X&iOS),Androidブラウザの挙動
先にWebkit系の挙動について説明します。先にも上げたとおり、Webkit系のブラウザは小数点以下を切り捨てて表示させるため、49.5pxは49pxに、50.5pxは50pxとなり、満たない場合は少し隙間ができ、はみ出した場合はちょうど収まるようにレンダリングされます。
Chrome(mobile), Opera, IEの挙動
それでは、先の例ではうまい具合に調整してくれたChromeなどのブラウザの挙動はどうなるでしょうか。結論から言うと通常Firefox以外は49.5px以上50.5未満なら50pxとしてレンダリングされます。とすると、デモページの例で言うと49.5pxの場合はうまく収まり、50.5pxの場合は1pxはみ出して表示されます。付け加えると、49.5未満の場合は、1px隙間があるように見えます。下記はOperaでのレンダリング例です。
また上記のブラウザでも、それぞれ認識できる桁数が違うため例えば、width: 100.998877%
などとすると細かく違ってきます。認識できる桁数については、[CSSの小数点以下の数値を各ブラウザはどのように解釈するか(http://unformedbuilding.com/articles/after-the-decimal-point-in-css/)]で詳しく解説されています。
Firefoxの挙動
この場合、Firefoxのみディスプレイのピクセル密度にあわせてサブピクセルまでレンダリングされます。下の画像はRetinaディスプレイの際とピクセル密度86ppiの普通のPCディスプレイの際のFirefoxでのレンダリング例です。
普通のディスプレイの方では、chromeやOperaと同様の表示なのですが、Retinaディスプレイだとサブピクセルも忠実にレンダリングし、0.5px分隙間が見えたり、はみ出て見えると思います。ちょっと上記の画像だと分かりにくいので、49.5pxの方にborder-right
を追加してみると分かるのですが、ボーダーが.5px分だけはみ出てちょうど1pxボーダーの真ん中に親要素の境界が来る感じになります。
まだ0.5px程度だと分かるんですが、それ以下だとなかなか注意してみないと気付かったりするので意図してない場合は注意が必要ですね。
ブラウザのズーム機能利用時について
これまでいずれも、ブラウザの表示倍率が100%の際のレンダリング例を上げてきましたがズーム機能を利用するとどう変わってくるのでしょうか。
Safari(OS X&iOS),Androidブラウザの挙動
Webkit系のブラウザには、iPhoneに搭載されているSafariやAndroidブラウザが含まれているためズーム機能を使うユーザがデスクトップ版に比べて多いのでは無いでしょうか。これらの場合、切り捨てているため、表示倍率が変わってもレイアウトが変わることはありません。詳しく調べていませんが、むしろこのためにズバッと切り捨てているのでは無いかと思います。ただ難点が、最初の子要素の幅の合計が親要素の幅と一致する場合のHTMLをズームしてレンダリングすると要素間にぼんやりと隙間があるように見える時があります。下記はSafariでのレンダリング例です。
Chrome, Opera, IEの挙動
表示倍率が100%の際は、±1pxの間は整数の値としてレンダリングしていたChrome,Opera,IEのブラウザは、表示倍率を変えるとまた違ってレンダリングするようになります。例えば下記はIE11で表示倍率を200%にした例ですが、width: 99% = 49.5px
の場合も隙間があるようにレンダリングされます。
ここもズーム機能について詳しく調べていませんが、49.5px * 200% = 99px
とレンダリングされるのではないかと思います。これは整数にならなくても±1pxの範囲を超えるとそのようにレンダリングされますので、表示倍率150%の際も同様です。
Firefoxの挙動
Firefoxは表示倍率100%の際と変わらずにレンダリングします。
まとめ
上記で上げた記事や、文末に掲載する参考記事でも述べられていますが特定の幅のみに対応するのではなく、未知のデバイスのディスプレイサイズへの対応を考えたレスポンシブデザインでは、リキッドデザインが用いられますが、その場合多くのレイアウトが小数点の数値を持つ可能性があります。その場合は、上記の挙動をよく理解することが重要な気がしています。
またいわゆるデスクトップのサイズのディスプレイにのみ対応する場合は、むやみにサブピクセルが発生するレイアウトの仕方をせず、きっちり整数のpx単位でレイアウトを組むことが大事では無いでしょうか。ちなみに私は今回はこれでミスをして調べ始めました。
参考