paddingとmargin相殺

CSSを理解する上で欠かせない要素がマージンとパディングです。

padding と margin

各要素は、マージンとパディング、そしてwidthというプロパティを持ちます。これは要素の配置に関連するプロパティです。まずは図をみてください。

padding.png

マージン(margin)は余白に相当します。他の要素と自分のブロックの隙間(マージン)をどれくらい取るべきかという指定です。

パディングは自分のブロック内の要素を表示するとき、内側に向けてどれだけ位置を詰めるか(どの部分を表示領域とするか)を指定します。

なぜ似たような指定が2つあるのかということですが、これには意味があります。

  • border(枠線)は margin の内側で padding の外側(2つの境界)に配置される。
  • padding は指定した値だけ必ず領域が確保されるが、marginは相殺される

marginの相殺

上の図で、div(A) の margin-bottom が "20px"、div(B)の margin-top が "10px" のとき、この2つdivブロックの空間は20pxです。10+20=30pxと思った人は間違えです。margin は2つの領域間の「空間の最低値」を指定するものだからです。

margin-bottom: 20px; → 下の要素と最低でも20pxは開けなさい

margin-top: 10px; →上の要素と最低でも10pxは開けなさい

という意味になります。

では次の図とCSSのとき、x, y の長さはそれぞれ何pxになるでしょうか?

margin.png

div.C { border: 1px solid blue; margin-bottom: 15px; }
div.A { border: none;           margin-top: 10px; }
div.B { border: 1px solid blue; margin-top: 15px; }

x の長さはすぐに分かりますよね。div.C の 15px と div.A の 10px で大きい方になりますから「x=15px」です。ではyはどうなるでしょうか? 正解はy も 15px です。つまり、この場合div.Aの上辺とdiv.Bの上辺は一致してしまいます

テーマを作成しているときに陥りやすい問題なのですが、子要素div.Cのマージンは親要素にpaddingもborderもないとき親要素のマージンを含めて他の要素と相殺します。別の言い方をすれば、中身のない要素同士は中身のある要素を見つけるまでどこまででもマージンを相殺します。

adiaryのテーマCSSをみていると、よく「padding: 1px;」という表記を見つけるのですが、これは内部の子要素がさらに外側のマージンまで相殺しないようにする工夫(細工)です。代わりに枠線(border)を付けても同じ作用を起こせますが、枠線は表示されてしまうため、(枠線を出したくないところでは)paddingを使って不用意な相殺が発生しないようにしています。

ここでは相殺を上下方向についてのみ説明しましたが、左右についても全く同じことが起こります。

ブロックのwidthとIEのバグ

ブロック(要素)の横幅を固定したいときはCSSの「width」プロパティを使います。例えば、横幅800px固定のテーマなど、この指定は非常によく使われます。

div-width.png

CSSにおけるwidthは該当ブロックからborderの太さとpaddingを除いた内部の横幅として定義されています。borderとpaddingはwidthに含まれないということを理解しておいてください。

ただしIE(の後方互換モード)ではこの解釈にバグがありborderとpaddingを含んだ幅をwidthとして指定します

ですから、ある要素をIEとそれ以外のモダンブラウザで正しく表示するためには、paddingとborder、widthの単位系をすべて統一して次のように細工しなければなりません。

div.w800 {
	padding: 1em 10px 1em 20px;  /* 上, 右, 下, 左 */
	border: 1px solid blue; 
	width: 728px; /* 800 - 20 - 10 - 1*2 = 728 */
	_width: 800px; /* IEでのみ有効な属性値 */
}

またIE6においてwidth値が瞬時に決まらないと表示されたり/消えたりするバグがあり、不必要に_widthを人間が計算して予め書いておく作業が必要になることがあります。