レスポンシブなデザインにするなら知っておきたい。各ブラウザの小数点以下のピクセル値の扱い

Advertisement

デザイン要素を固定しないリキッドレイアウトは、未知の端末にも対応するというコンセプトのもとに実装するレスポンシブウェブデザインには必須だと考えています。そのリキッドレイアウトを実装する際に理解しておきたいのが、パーセント値で幅や高さを指定した際に小数点以下になるピクセル値(10.5pxとか9.2pxなど)に対するブラウザの挙動です。

たとえばグリッドシステムを構築する際、計算上はあっているのにブラウザでは思った通りに表示されないといったことが起こります。これは、各ブラウザのサブピクセル(小数点以下のピクセル値)の扱いの挙動差により生まれます。

まずはパーセント指定の基本から

まずは前提となるパーセント指定の際の計算の基本のおさらいから。。。
CSSでパーセント値を使って幅や高さ指定をすると、指定した要素を含む親要素をベースにピクセル値が計算されます。

たとえば100pxの親要素の中にある子要素に30%の幅を指定すると、30pxになります。以下のような感じですね。これだと、サブピクセル(小数点以下のピクセル値)が出ないので、各ブラウザの挙動は同じになります。

 
<div style="width:100px;background:#ddd;height:100px;margin:0 0 30px;">
  <div style="width:30%;background:blue;height:100%;">&nbsp;</div>
</div>

では、子要素に33.33%や33.5%を指定するとどうでしょう?

小数点以下のpx値の扱いはブラウザによって異なるため、以下のようにそれぞれ違った計算がされます。

WebkitとOpera

小数点以下は切り捨て

  • 100px x 33.5% = 33.5px → 33px
  • 100px x 33.33% = 33.33px → 33px

[追記: 2012/6/2]
はてブで「Chrome 21 から Firefox, IE9, IE8 と同じになるみたいですよ。」というコメントをいただきました。Mac Chrome 21.0.1155.2 devでデモページを見たら、たしかにFirefox、IE9、IE8と同じになっていました。これは嬉しいですね。コメントを入れていただいたcheesesouffleさんに感謝です。

Firefox、IE9、IE8

自動でピクセル値を計算、調整する

  • 100px x 33.5% = 33.5px → 33pxまたは34px
  • 100px x 33.33% = 33.33px → 33pxまたは34px

IE7、IE6

0.5以上を繰り上げ

  • 33.33% x 100px = 33.33px → 33px
  • 33.5% x 100px = 33.5px → 34px

たとえば、この記事の例にあるように、49pxと50pxの親要素のなかに25%の子要素を4ついれた場合、以下のような結果になります。

計算上は各カラムの幅は以下のようになりますが、ブラウザの共同差により実際の表示は異なります。

  • 49px x 25% = 12.25px
  • 50px x 25% = 12.5px

WebkitとOpera

どちらも小数点以下が切り捨てられるため、以下のようにピクセルが余ってしまいます:

[追記: 2012/6/2]
はてぶで「Chrome 21 から Firefox, IE9, IE8 と同じになるみたいですよ。」というコメントをいただきました。Mac Chrome 21.0.1155.2 devでデモページを見たら、たしかにFirefox、IE9、IE8と同じになっていました。これは嬉しいですね。コメントを入れていただいたcheesesouffleさんに感謝です。

Firefox、IE9、IE8

自動で調整してくれるため、親要素に子要素がぴったりはまります:

IE7、IE6

小数点以下が0.5以下の場合、ピクセルが余ってしまいます。逆に小数点以下が0.5以上の場合、繰り上げになり一番右のカラムが落ちてしまいます。:

デモページはこちらからどうぞ。

グリッドレイアウトでの2つの問題点

グリッドレイアウトを構築する際、これらブラウザの挙動による問題点が2つあります。

  1. WebkitとOperaで、ピクセルが余る
  2. IE6、IE7で、カラムが落ちる

上記2つの問題点に対して、完璧ではないですが、対処法として以下が考えられます。

WebkitとOperaで、ピクセルが余る

レスポンシブWebデザインのフレームワーク「Foundation」で採用しているように、最後のカラムを右寄せにする。こうすることで、全体幅を統一して見せることができ、ある程度デザインの統一感は保てます。

下図のように、一番右のカラムの左の空きが大きくなってしまいます。

IE6、IE7でのカラム落ち

IE向けのCSSでは、繰り上げが起こらないように、0.5px分を幅から引きます。たとえば100pxの親要素に入った要素の場合、0.5 ÷ 100 = 0.5%を幅の指定値から引きます。

これで、IE6、IE7でもWebkitやOperaと同じ挙動になるので、扱いが楽になります。ちなみに、親要素も%指定の場合、最小幅で上記の計算をすればカラム落ちの心配は無くなります。一つ一つ計算していくのは大変なので、Tateさんが紹介しているようにLESS.jsSaSSのようなCSSフレームワークを使えたら、ある程度のコーディングの効率化はできそうです。

まとめ

レスポンシブWebデザインでウェブサイトを構築する際、リキッドレイアウトは必須の条件だと考えています。そして、リキッドレイアウトを実装するにはCSSでのパーセントの幅指定は必須になります。予期せぬレイアウト崩れを極力避けるために、こういった細かいブラウザの挙動は必須の知識になりそうですね。(地道な作業だな〜。。。)

参考リンク

【宣伝】レスポンシブWebデザインについての本を書きました

[追記: 2013/1/4]

レスポンシブWebデザインに関する本「レスポンシブWebデザイン 制作の実践的ワークフローとテクニック」を書きました。1年以上レスポンシブWebデザインで作ったウェブサイトを運営した経験から試行錯誤したことを1冊の本にまとめました。良かったら立ち読みしてみてください。こちらで第1章の一部を公開しています。あと、本書の見どころ・読みどころをまとめたスライドを作ったので、良かったらあわせてご覧ください。

“レスポンシブなデザインにするなら知っておきたい。各ブラウザの小数点以下のピクセル値の扱い” への8件のフィードバック

  1. […] ただ、今回は割り切れるから良いのだけど、小数点以下のピクセル値の扱いは各ブラウザによって違うようなので、注意が必要かも。 […]

  2. mameshiba より:

    はじめまして。
    渡辺さんが執筆されました書籍「レスポンシブWebデザイン – 制作の実践的ワークフローとテクニック」を購入しまして、レスポンシブについて勉強しています。

    http://rwd-book.info/download/index.shtml 

    上記URLからダウンロードしました”grid-calc.xlsx”この中にあります「in cols adjust」というのは、何を意味しているのでしょうか。
    この数値が入れ子カラムの幅調整で使われていますが、なぜ入れ子の時にこの調整値が必要なのか教えて頂けませんか?

    • ryo より:

      mameshibaさん、
      はじめまして。
      拙著の購入ありがとうございます!そして、詳しく読んでいただきありがとうございます。著者としては嬉しい限りです。

      さて、ご質問の「in cols adjust」ですが、この数値はIE向けに調整したカラム幅(エクセルの「ie adjust」)でガッターサイズの%値を再計算した数値と、この投稿で説明しているIE6、7の小数点以下のピクセルの扱いを補正する調整値を合計したものです。

      IEではbox-sizingがサポートされていないため、入れ子になるカラム幅からガターサイズを引いた値を指定する必要があります。カラムを入れ子にする際は、親要素の幅がIE向けに調整された値になるため、親要素をベースとするガッターサイズの計算もその都度やり直す必要があります。そのため、「in cols adjust」のような計算をしています。

      ※box-sizingについてはp.214の図 5.4.4cとp.217の「3. IE7向けのCSSを別途記述する」をご参照ください。

      in cols adjust = 再計算したガッター幅の%値 + 小数点以下のピクセル値の扱いを補正する調整値の%値

      たとえば、12カラムのグリッドに入れ子する場合、親要素の幅は1140px × 98.2018% (エクセルの「ie adjust」カラムの「twelve」の数値)になります。そのため、ガッター幅(ここでは10px)の%値は以下のような計算になります:

      10px × 2 ÷ (1140px × 98.2018% + 10px × 2)

      繰り返しになりますが、このガッター幅に、調整値(0.5px ÷ 1140px)を足したものが「in cols adjust」にある値です。

      同じように、たとえば10カラムのグリッドに入れ子をする場合、以下のような計算になります。

      ガッター幅の%値の再計算:
      10px × 2 ÷ (1140px × 81.5351% + 10px × 2)

      ※81.5351%は、エクセルの「ie adjust」カラムの「ten」の値です。

      この値に、調整値を足したものが「in cols adjust」の値になります。

      だいぶややこしいですが、おわかりいただけたでしょうか?
      よろしくお願いします。

      • mameshiba より:

        渡辺さん、お忙しい中ご丁寧に解説頂きありがとうございます。

        また質問で申し訳ないのですが、ChromeやSafariなどのモダンブラウザは、入れ子・非入れ子に関わらず横幅の値は、「column」の値(8.3333%や16.6667%など)を使っていき、一方IEはborderやPaddingの値も横幅に内包されてしまうので、予めそれらを差し引いた横幅にする必要があり、その差し引く必要のある値が「in cols adjust」という考え方でよいでしょうか。
        理解が悪くすみません。。。愚問を投げておりますこと自覚しておりますので、お手透きの際でけっこうでございます。

        • ryo より:

          mameshibaさん、
          ご理解いただいている通りです。

          ブラウザごとのCSSの解釈が微妙に異なるため、ややこしい対応が必要で、僕もこれらを自分の頭の中で整理するのに時間を要しました。愚問だなんてとんでもないです。

          • mameshiba より:

            渡辺さん、お忙しい中教えて頂きましてありがとうございました!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です