CSSデザインノートでタグ「margin collapsings」が付けられているもの

当blogの以下の記事(4.マージンボックス)でも紹介しているように、隣接しているあるいは入れ子になっているボックスにおいて、垂直方向のmarginは相殺されます。marginが相殺されることをmargin collapsingsというらしいです。

ここではdivのボックスの中にp要素が二つ通常フローで流し込まれているときに、どのように垂直marginの相殺に気をつけて余白をとるか考えてみます。

サンプル

サンプルボックス

div要素をボックスA、上段のp要素をボックスB、下段のp要素をボックスCとしたとき、ボックスAとボックスBあるいはボックスCの関係は「入れ子」関係にあります。一方、ボックスBとボックスCの関係は「隣接」関係にあります。

「入れ子」関係にある場合は、内包している要素、つまりボックスAにpaddingを指定して余白を設けます。

「隣接」関係にある場合は、隣接する側には片方のブロックだけにmarginを指定して余白を設けます。

(X)HTMLコード

<div>
   <p>
      ボックスB
   </p>
   <p>
      ボックスC
   </p>
</div>

CSSコード

div {
   padding:10px;
   background:#E2DEDF;
}

p {
   margin:0 0 10px 0;
   background:#FFCAD8;
}

サンプル

サンプルボックス

しかしこれでは、下段のp要素の下に必要以上に余白が空いてしまいます。なので、下段のp要素だけ「class="bottom"」を記述し下方のmarginを0にします。

(X)HTMLコード

<div>
   <p>
      ボックスB
   </p>
   <p class="bottom">
      ボックスC
   </p>
</div>

CSSコード

div {
   padding:10px;
   background:#E2DEDF;
}

p {
   margin:0 0 10px 0;
   background:#FFCAD8;
}

p.bottom {
   margin:0;
}

CSSでテンプレート(段組レイアウト)を作成する場合、ボックスモデルの理解はかかせません。

段組レイアウトでは、段組を例えばdiv要素などのブロックレベル要素で枠を作ります。ボックスは以下の4つの領域から成ります。

  1. コンテンツ(内容)ボックス
  2. パディングボックス
  3. ボーダーボックス
  4. マージンボックス

1.コンテンツ(内容)ボックス

テキストや画像などの領域です。widthとheightで領域を指定します。

2.パディングボックス

線の領域より内側の余白です。paddingで領域を指定します。

3.ボーダーボックス

線の領域です。borderで色、太さ、線の種類を指定できます。

4.マージンボックス

線の領域より外側の余白です。marginで領域を指定します。

注意すべき点は、隣接するブロック間の縦方向のマージンは「相殺する」ということです。

例えば、AとBというボックスがあって、Aのマージンが30px、Bのマージンが50pxの場合は、その間の余白(マージン)は50pxになります。両方が正のマージンの場合、その大きい方のマージンが指定されます。

Aのマージンが-30px、Bのマージンが50pxの場合は、その間の余白(マージン)は20pxになります。片方が負のマージンの場合、両方のマージンを足した値が適用されます。

Aのマージンが-30px、Bのマージンが-50pxの場合は、その間の余白(マージン)は-50pxになります。両方が負のマージンの場合、その小さい方のマージンが指定されます。

マージンの相殺については仕様書を参考にしてみてください。

モードの違い

比較的新しいブラウザは、DOCTYPE 宣言によって「標準準拠モード」「ほぼ標準準拠モード」「後方互換モード」というレンダリングが変わる機能がついています。

「ほぼ標準準拠モード(Almost Standards Mode)」というのは、"ほぼ"標準準拠ですがテーブルセル内の画像のレイアウトが後方互換の拡大解釈を行うというものです。

「標準準拠モード」と「ほぼ標準準拠モード」では、widthおよびheightはボックスの大きさはコンテンツ(内容)ボックスの大きさになります。

標準準拠モード

しかし、「後方互換モード」では、コンテンツ(内容)ボックス領域の幅の中に、パディングボックス領域およびボーダーボックス領域が含まれてしまいます。つまり、widthの中にpaddingとborderの大きさが含まれてしまいます。

後方互換モード

「標準準拠モード」になるDOCTYPE 宣言には以下のようなものがあります。ただしブラウザによっては「ほぼ標準準拠モード」にもなる場合があります。

XHTML1.0 Strict
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
XHTML1.0 Transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
HTML4.01 Strict
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
HTML4.01 Transitional
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

DOCTYPE 宣言はあくまで、レンタリングを変えるのが目的ではなくHTMLのバージョンを示すことだと言うことは忘れないでください。

また、XML 宣言の有無にもよって、モードが切り替わる場合があります。

IE6ではDOCTYPE 宣言の前に何か書かれていると「後方互換モード」になるという仕様があって、XML 宣言を記述してしまうと仕様のとおり後方互換モードになってしまいます。

もし、後方互換モードにしたくない場合は、

  1. XML宣言を記述しない。XHTMLの場合は文字コードがUTF-8あるいはUTF-16であれば、XML宣言を省略することができます。
  2. XHTMLではなくHTMLで記述する。

などの方法があります。

ちなみに私は、基本的にXML宣言あるなしに関わらず極力「標準準拠モード」でも「後方互換モード」でも同じレイアウトになるようにコーディングしています。

ポイントは「ひとつのボックスに対してwidthと一緒にpaddingやborderを指定しない」と言うことです。widthしか指定しないdivボックスを作成し、その中のdivタグやpタグなどにpaddingやborderを指定するようにしています。

最近のブログ記事