ボックスモデル
ブラウザーが文書をレイアウトする際には、それぞれの要素を「CSSボックスモデル」に基づいた長方形のボックスとして描画します。
CSSでは、このボックスに対して、寸法、位置、背景、境界線などを指定していきます。
このボックスは、下図のような4つの領域で構成されています。

コンテンツ領域
上の図では白背景になっている部分をコンテンツ領域と呼び、この部分に実際のコンテンツが描画されます。
パディング領域
上の図ではピンク背景になっている部分で、境界線(ボーダー領域)の内側にある余白のことをパディング領域と呼びます。
パディング領域の幅・高さは padding-top、 padding-right、 padding-bottom、 padding-left の各プロパティおよび一括指定プロパティの padding で決定されます。
ボーダー領域
上の図では紺色背景になっている部分で、いわゆるボックスの境界線部分のことをボーダー領域と呼びます。
境界線の幅は、 border-width および一括指定プロパティの border で決定されます。
ボックスに対して、背景はボーダー領域の部分まで拡張されます。
なお、background-clip プロパティで「コンテンツ領域のみ」や「パディング領域まで」に変更するも可能です。
マージン領域
上の図では緑背景になっている部分で、境界線の外側に設ける余白部分のことをマージン領域と呼びます。
通常は隣の要素と間隔を開けるための空の領域として使用します。
マージン領域の寸法は、 margin-top、 margin-right、 margin-bottom、 margin-left の各プロパティおよび一括指定プロパティである margin で決定されます。
要素の実際の大きさ
要素の寸法は width、 min-width、 max-width、 height、 min-height、 max-height の各プロパティによって指定しますが、これらのプロパティで指定した値が、実際にどの部分の寸法になるかは、 box-sizing プロパティの値によって、指定の仕方が変わります。
content-box の場合(規定値)
この場合は、「コンテンツ領域」の大きさを指定したことになります。
border-box の場合
この場合は、「ボーダー領域」の大きさを指定したことになります。
See the Pen ボックスモデル by Masahiko Iwakiri (@m-iwakiri) on CodePen.
上のサンプルでは、2つのボックスは「box-sizing プロパティの値以外同じ」にしてありますが、box-sizing プロパティの値が違うと、このように違いが現れます。
インライン要素の場合
インライン要素の場合も、考え方としては変わりませんが、インライン要素はあくまでも「行内に配置される要素」のため、設定しても無視されるプロパティがいくつかあります。
上のサンプルにあるように、width や height で幅や高さを決めることは出来ず、上下のマージンは指定しても無効になります。高さに関しては、line-height プロパティで設定した高さとなります。
上下パティングは一応設定できますが、それによって行間のサイズが変わるようなことはないので、上下パディングを設定した分だけ、前後の行と重なって表示されています。
マージンの相殺
先程のサンプルを見ると、少々不思議に見える部分があるかもしれません。
1つ目のボックスと、2つ目のボックスには、【上下左右それぞれに20pxのマージン】を設定しています。
それならば、1つ目のボックスと、2つ目のボックスの間は【20px + 20px = 40px】空いていても良いはずですが・・・実際にはそうなっていません。(1つ目のボックスの上余白と見比べると分かりやすいかと思います。)
実際には、【1つ目のボックスの下余白】と【2つ目のボックスの上余白】が重なって表示されているのですが、この現象のことを【マージンの相殺】と呼んでいます。
なお、マージンの相殺は【上下のマージン】の場合だけ発生するので、左右のマージンが重なり合うようなことはありません。
なお、マージンの相殺が発生するには、いくつかの条件があります。
- 隣接する兄弟要素
- 親要素と先頭の子要素・末尾の子要素
- 空の要素
隣接する兄弟要素の場合
See the Pen マージン相殺1 by Masahiko Iwakiri (@m-iwakiri) on CodePen.
親要素と先頭の子要素・末尾の子要素
このパターンは少々厄介なパターンで、下記のように定義されています。
ブロックが、その margin-top とその先頭の子要素の margin-top を分けられるような、ボーダー、パディング、インラインコンテンツ、フロートの解除 (clear) のいずれも持たない場合、もしくは、ブロックがその margin-bottom とその末尾の子要素の margin-bottom を分けられるような、ボーダー、パディング、インラインコンテンツ、高さ (height)、高さの最小値 (min-height) のいずれも持たない場合、マージンは相殺されます。相殺されたマージンは最終的に、親要素の外側に出ます。
https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
どう厄介なのか、以下のサンプルを見ると分かりやすいかと思います。
See the Pen oNjdXJX by Masahiko Iwakiri (@m-iwakiri) on CodePen.
この例でいうと、グレー背景の <article> 要素にはマージンを設定していません。しかし、1つ目と2つ目の <article> 要素の間は空いています。もっというと、1つ目の <article> 要素の上も空いています。
一方、各 <article> 要素の最初にある <h1> 要素には、上下に30pxのマージンを設定しています。
さらに、1つ目と2つ目の <article> 要素には、padding-top も border-top も設定されていません。
そのため、<article> 要素の上マージン0pxと、<h1> 要素の上マージン30pxで相殺が発生し、<h1> 要素の上マージン30pxが上にはみ出てしまうのです。
それに対して、2つ目の <article> 要素と3つ目の <article> 要素、3つ目の <article> 要素と4つ目の <article> 要素の間には白い余白は見られず、<article> 要素の中で余白が空いています。
3つ目の <article> 要素には border-top が、4つ目の <article> 要素には padding-top がそれぞれ設定されていて、<article> 要素の上マージンと、<h1> 要素の上マージンを明確に分けられる領域が存在しています。そのため、マージンの相殺は発生していません。
空のブロック
中身が空っぽのブロックに対して、上下のマージンを設定した場合にも相殺が発生します。
See the Pen マージンの相殺3 by Masahiko Iwakiri (@m-iwakiri) on CodePen.
この例では、<p> 要素が実際は7つ並んでいて、それぞれ上下20pxのマージンが設定されているのですが、2つ目、4つ目、6つ目は空の <p> 要素です。
6つ目については、border を設定しているので、存在が分かりやすいですが、2つ目と4つ目の <p> 要素は一見存在しないように見えます。
空のブロックの場合も、下記のように定義されていますので、border や padding があるか否かで相殺が発生するかどうかが変わってきます。
ブロックが、その margin-top と margin-bottom を分けられるような、ボーダー、パディング、インラインコンテンツ、高さ (height)、高さの最小値 (min-height) のどれをも持たない場合、top と bottom のマージンは相殺されます。
ですので、2つ目と4つ目の <p> 要素については、margin-top と margin-bottom が相殺され、さらに隣接する兄弟要素の間でもマージンの相殺が発生するので、あたかも要素が存在しないように見えるようになっています。
マージンには【負の値】も設定できるのですが、負の値が絡んでマージンの相殺が発生した場合は、一番大きな正のマージンと一番小さな(もっともマイナスの)マージンの合計値になります。
例えば、-30pxのマージンと、30pxのマージンで相殺が発生した場合、【 -30px + 30px = 0px 】となるので、マージンが0となります。
浮動する要素 と 絶対位置指定された要素 の場合は、マージンの相殺は起きません。
MDN Web Docs: https://developer.mozilla.org/ja/
W3C仕様の正確な定義、最新情報は上記サイトをご覧ください。

コメント