CSS おれおれ Advent Calendar 2012 – 05日目
横幅いっぱいに広げようとしてwidth:100%
を指定したら横スクロールバーが出ちゃった、という経験ありませんか? その原因と仕組み、回避策についてお話しします。
わりとFAQな感じ。これは是非覚えておいてもらいたいです。というか知っておいてください。
はみ出した例
position:absolute
ないしposition:fixed
を使った際にこうなっちゃう事が多いと思います。
上部から出てきたメッセージ欄、横にはみ出てますね。
でも指定はちゃんとwidth:100%
です。「幅いっぱい」を指定しているのに、どうしてはみ出てしまったんでしょうか。
「幅」が意味するところ
実はCSSの仕様が定めるところの「幅」というのが、我々が視覚的に認知している「幅」と異なっているのが原因です。
ボックスモデル
CSSではこんなものを定めています。
いわゆるボックスモデルというやつです。
普通、人が領域を見て「幅」と認識するのは、枠線 (Border) までです。
ところがこのボックスモデルでは、幅と高さというのは内容 (Content) に対しての指定になります。
この認識の差が問題になります。
幅はwidth
だけじゃなかった
つまりContentの部分がきっちり横いっぱい100%
に広がって、さらにPadding分の幅も加わっていたのです。さらに指定があればBorder分、Margin分も広がります。
だからpadding:8px
とした場合、左右8pxずつ、合わせて16px分余計な幅が出来てしまうわけです。
回避策
はみ出させないようにするには、二つのやり方があります。
入れ子にする
width:100%
の指定とpadding
の指定が共存しているのが問題でした。
そこでwidth:100%
で横いっぱいに広げた要素の中で、幅を指定しないでpadding
だけ指定した子要素を設置します。(この場合はmargin
に置き換えた方が直感的かもしれません。)
内側の要素は幅を指定していないので、自動的にwidth:auto
になります。この場合はMarginまで含めた幅がいっぱいに広がるようになります。
外側にwidth:auto
を指定する、というのはうまくいきません。position:absolute
を指定している状態では、auto
は最大ではなく最小幅になるためです。
このやり方は古いIEでも正確に表現できるのですが、余分な要素が増えてしまうのが難点です。
box-sizing
を使う
先ほどのボックスモデルの説明でサイズの取り方が二通りあるという話をしました。box-sizing
というCSSプロパティを用いると、その二通りを指定する事ができます。
box-sizing:border-box
を指定する事で、width
(とheight
)で指定するサイズがBorderまで含めたものを指す事になりました。
このやり方が一番綺麗です。
IEは8以降が対応しています。7は対応していません。6は、対応はしていないのですが、最初からborder-box
の挙動になっています。(不具合でした。) 末尾の参考リンクのところにIE 7で動かせるようにしているページを紹介しています。
あとFirefoxではベンダープレフィックスが必要です。(Ver.1.0の頃からずっと……。)
あとあと、Android等ではちゃんと動くらしいです。ってばっちゃがゆってた。
ボックスモデルの考え方
これは仕様策定の様子を知る訳ではなくて、ただの当て推量ですが……。
何故このような「不自然」な仕様になっているかというと、おそらく見方を変えるとこの方が実は「自然」だからだと思います。
例えばContentが画像であった場合を考えると、こちらの方がしっくりくるのがわかります。
画像の幅と高さは如何や
画像に枠線を付けたとしたら、その枠線は画像の外側に付くべきですよね。内側に付くと画像にかぶってしまいます。
このとき幅と高さは、何を指定するべきでしょうか。100×100pxの画像に5pxの枠線を付けたとして、img
のスタイルwidth
とheight
に与えるべき数値は何でしょうか。
当然width:100px
, height:100px
ですよね。そして表示は100pxに両端5pxずつの枠が付いて、合わせて110px。これならしっくり来ませんか。
Paddingは余白じゃない
また、辞書で”padding”を引いてみると、余白ではなく「詰め物」という語で表されています。(”margin”だと欄外の余白ですね。)
つまり先ほどの例でいくと、Paddingは画像と枠線の間に詰めた隙間という事になります。これもまた、幅と高さに含めるのは不自然ですね。
という風に解釈しているのですが、いかがでしょうか。
まあ分かり辛いけどね
要素によって初期値を変えるとかでも良かったんじゃないかなーとか思わないでもないです。はい。
参考
- CSS Basic User Interface Module Level 3 (CSS3 UI)
- box-sizing – CSS | MDN … Mozillaの。日本語。
- 実験室: ボックスサイズの解釈はIE6の方がわかりやすいと思う | Mach3.laBlog … 図解と、IE 7でもどうにかするjQueryプラグイン。
- CSS basic box model … 仕様
- The various areas and edges of a typical box … ボックスモデルの解説図
- Box model – CSS | MDN … Mozillaの。日本語。