解 説

マージンの相殺について

上下のマージンは相殺される仕組みになっています。相殺によって、少ない方の数値が打ち消されます。

次のような例を考えてみましょう。

CSSの設定

HTMLの設定

上の例では最初のdivのマージンは上下20px、次のdivのマージンは30pxです。「ああああああ」と「いいいいいい」の間には50pxのマージンが空きそうですが、実際は30pxしか空きません。相殺によって、少ない方の数値が打ち消されたのです。これがマージンの相殺です。

ブロック要素では通常フローしたブロック要素は必ずその下に次のブロック要素が来ます。その為通常フローしたブロック要素同士の場合は上下のマージン相殺しか起こりません。つまり横には並ばないので左右のマージン相殺はそもそも起こらないのです。
ではフロートして横並びにした場合は親、子に関わらずmarginを指定している要素に、floatを適用すると相殺をしなくなります。

ここまでは少し勉強した方はよくご存知のことですね。

入れ子状態のマージンの相殺について

悩ましいのは親子関係の入れ子状態にある場合のマージン相殺です。上下のマージンの相殺はちょっと複雑な挙動になります。ただし、横方向のマージン相殺はありません。

次の例をみてください

この部分がヘッダー

上のサンプルのソースは以下です。

CSS側

HTML側

ブロック要素を入れ子状態にして内側のブロック要素「この部分がヘッダー」に上マージンを設定して30pxだけ空間を空けたいと思うのだが、ブロック内でマージンがかかりません。本来なら30pxだけ空間が空いて水色の背景が30pxだけ見えるはずなのですが、「この部分がヘッダー」に変化は見られません。
そして、さらに外側のマージンよりも内側のマージンが大きければ内側のマージン分だけ、ここでは30pxだけ外側にマージンがついてしまうという変な挙動になってしましいます。

この入れ子状態のマージン相殺は制作の時の悩みの種になることが多いです。しっかり理解しておきましょう。

解決方法は外側のブロック要素にボーダーをつけるか、paddingをつけます。
先ほどの例で外側のdivにボーダーをつけてみましょう。以下のとおりです。

この部分がヘッダー