タオルケット体操

サツバツいんたーねっと

CSSのわからないを解決する基礎知識 ボックスモデル編

テーブルレイアウトから抜け出せないエンジニアがとりあえず最低限押さえるべき仕様 - タオルケット体操

上の記事の続きです。

例によってざっくりなので、この記事で概要を掴んだ後にちゃんとした仕様なりリファレンスを読むことを推奨します。

この記事を読むと出来るようになること

  • 自分が書いたタグとCSSが画面上にどういうスペースを占有するのか理解出来るようになる

  • marginとpaddingを使いこなせるようになる

  • width: 100%;なのになんか横にはみ出すんだけど(ブチ切れ)に対処出来るようになる

  • border入れただけでなんで描画崩れるのCSSなんなのクソなの?に対処出来るようになる

ようになります。

はじめに (widthを100%にしたのにはみ出る現象)

まずはこいつをみてくれ、どう思う?

f:id:hachibeechan:20141029144832p:plain

こいつに適用しているCSSはだいたいこんな感じになります。

.hoge {
  border: 2px solid red;
  margin: 3px;
  padding: 5px;
  background-color: blue;
  width: 300px;
}

この要素が占有する幅はいくつでしょうか。「width: 300pxだから300pxじゃないの」だと思った人は、そのうち「width: 100%;なのになんか横にはみ出すんだけど(ブチ切れ)」と言い出してモニターをブチ割る羽目になります。

height, widthが指定するのはcontent areaの大きさである

はい。
content areaとは、上のクロームの画像だと300 × 189って書いてある青色の四角(ボックス)のことです。

そして、ここが大事なのですが、要素が占有する大きさは「(height or width) + padding + border + margin」で決まります。人間が直感的に考える大きさは、「(height or width) + padding + border」です。
ここテストに出るからな。

つまり「親の大きさに合わせてwidthを設定したのになんで横スクロールが出てくるんだよ!!!」という現象は、paddingとborderとmarginを合わせた幅が親要素より大きくなってしまっているからなんですね。
「marginはまだいいけど、paddingは変な挙動するから使いにくい」と言うデザイナーの方は結構いるみたいですが、marginと違ってautoを指定出来ないpaddingは、ボックスモデルを理解しないまま余白調整に使うと破綻しがちなので気をつけましょう。

なので、ぴったりwidthを設定したのに何故かはみ出る時はpadding, border, marginの幅を計算に入れた上で指定しなおしましょう。なおIE6はここの仕様が違うのですが、バグというよりはCSS2.1の仕様が生まれる前のブラウザであるがゆえの挙動らしいです。

なお、そのうち説明しますが要素がはみ出た際の挙動はoverflowプロパティで指定することが出来ます。特にoverflow: hidden;は個人的に結構よく使うので覚えておいて損はないでしょう。

ボックスを構成する各領域の説明

では、外側からします。

margin

一番外側にあるアレですね。
背景的なもの(上の例だとbackground-color: blue;ですね)はこの領域には適用されません。autoを指定すると色々よしなにしてくれて便利です。

こいつの厄介なところは、マージンの相殺と呼ばれる仕様にあります。
上下で相殺されたり、子要素のマージンが外側にはみ出したり、でも親要素にpaddingかborderを指定するとはみ出さなくなったり……。条件が多すぎて説明がめんどくさいので、これに関しては都度仕様を読むのが良いとおもいます。何度も書いてれば、そのうちマージンの挙動が『頭』じゃなくて『心』で理解出来るようになるはずです。

なお、Chromeなんかは「何も描画するものがないmarginの画面外へのはみ出し(右側や下側への余計なmargin)」は勝手に切り捨てられますが、他のブラウザは律儀に描画しようとするので環境ごとの違いが出る……と思っていたのですが、今Firefoxで試してみたところそんなことはなかったので、僕の勘違いか修正されたのかのどちらかだと思います。

border

枠線ですね。
透明色や、破線なんかを指定するとわかりますがこの領域までは背景の描画が行われます。

割と初心者殺しで、borderのせいで1pxずれるような現象はチャメシインデント。CSSから逃げるためにテーブルレイアウトを使っている種もみエンジニアも、このborderが領域を持つことによる位置ずれやはみチンに苦しめられることになります。逃れられない!(カルマ)

padding

borderとcontent areaの間にある余白部分です。背景の描画が行われます。

ボタンの様な要素の大きさを調整したい時など、登場の機会が多いプロパティでもあります。間違ってもフォントサイズを調整したbrタグを入れたり、 で幅を調整したりすることはないようにしましょう。

content area

テキストとか画像とかそこらへんが描画される領域ですね。heightとwidthで指定するのがここの大きさになります。当然背景の描画を行います。

インライン要素の場合はheightやwidthを指定出来ない(ブロック要素とかインライン要素とかについては以前の記事を参照)のですが、font-sizeline-height、コンテンツの長さで自動的に決まります。細かいルールは説明するのがしんどいので仕様を読んでください。

対抗策

正直、paddingとかを計算してwidth: 964px;なんて書くのはだるいので、楽に書けるようにする案を考えてみます。

頑張る

だるいとか言わずに頑張れ

メタCSS

今どき生でCSSを書く人はあまりいないと思うので、SASSとかStylusとかを使って適当にいい感じにしてくれるmixinとかを作ります。

CSS3

box-sizing: border-box;を使います。

box-sizingに設定出来る値には

  • content-box

    デフォルト

  • padding-box

    width, heightプロパティによって定義される領域にpaddingを含む

  • border-box

    width, heightプロパティによって定義される領域にpaddingとborderを含む(旧IEと同じ挙動)

の3つがあります。

border-boxについてだけ説明してる記事が多いですが、padding-boxなんてもんがあるんですね。
だいぶ直感的な指定が出来るようになるとは思います。

まだ草案段階のプロパティなので僕はあまり使いたくないのですが、一応IE8以上から対応しているのでどうしてもめんどくせーって時は選択肢に入ると思います。

おわりに

大体こんな感じです。

ボックスモデルをちゃんと理解しておけば、要素がはみ出したー! とか段組みが崩れんだけどー! みたいな現象にも、プロパティ調整したり、いい感じに要素をラップしたり、overflowを設定したりという正攻法で対処出来るようになるかと思います。

が、floatを使ってレイアウトするようになるとまた謎現象が起きるようになるので、次は気が向いたらfloat編について書きます。

以上。