CSSのmargin-topやmargin-bottomが効かない!marginの相殺とは

CSSのmargin-topやmargin-bottomが効かない!marginの相殺とは

margin-topやmargin-bottomが効かず、意図した余白ができなくて困ったことってありませんか。
それは、もしかしたら「marginの相殺」が起こっているのかもしれません。

私はコーディングを始めたばかりの頃、marginが相殺される場合があることを知らず、バグでも起こっているのかと思い、調べる方向性を間違えて無駄に時間を費やした思い出があります。
この記事では、marginを指定する際に絶対におさえておきたい、「marginの相殺」についてご説明します。

「marginの相殺」とは

「marginの相殺」とは何か?
それは、下のようにmarginの小さい方が大きい方に含まれて帳消しされてしまうことです。

上は、「Box01にmargin-bottom:100px」を、「Box02にmargin-top:50px」を指定した場合ですが、実際に効くmarginは、「Box01のmargin-bottom:100pxだけ」になります。
下のように150px余白がとられるようなことはありません。

「marginの相殺」は、縦のmarginが重なるところで起こる

「marginの相殺」は、「ブロックレベル要素」の「」の「marginが重なる」場合に起こる現象です。

  • 「ブロックレベル要素」
  • 「縦」
  • 「marginが重なる」

この3つが揃ったときに「marignの相殺」は起こります。

ブロックレベル要素

htmlの要素はブロックレベル要素とインライン要素に分類できて、ブロックレベル要素は、sectionタグやdivタグ、h1などの見出しタグ、pタグなど、ページを構成する上でのひとつの塊の要素です。

ちなみにインライン要素とは、spanタグやimgタグ、strongタグなど文章や文章の一部として扱われるようなものです。HTML5だとフレージング・コンテンツに属する要素のことです。

縦のmargin、つまりmargin-topやmargin-bottomで「marginの相殺」は起こります。
横のmargin(margin-leftやmargin-right)では起こりません。

marginが重なる

「marginが重なる」については、実際にサンプルを見た方が理解しやすいと思います。
以下に、「marginの相殺」が起こっている実例を挙げていきますので、marginの重なりについて具体的に見ていきましょう。

上下に隣接したボックス間のmarginの相殺

上下に隣接したボックス間で「marginの相殺」が起こります。

Sample01:「marginの相殺」が起こっていない状態

まず、「marginの相殺」が起こっていない状態を見てみましょう。
下記は、上下に隣接した赤と青のボックスの間に50pxの余白をいれています。

See the Pen sample01 by natsuki (@natsukimemo) on CodePen.

HTMLは隣接したdivタグに、クラスbox01とbox02を指定しています。

<div class="box01">
  <p>box01</p>
</div>
<div class="box02">
  <p>box02</p>
</div>

CSSは下記12行目、box01にmargin-bottom:50px;を指定しています。
これによって、2つのボックス間に50pxの余白がとられています。

*{
  margin:0;
  padding:0;
  font-size:30px;
  color:green;
}
div{
  width:300px;
}
div.box01{
  background-color:red;
  margin-bottom:50px; 
}
div.box02{
  background-color:blue;  
}

【補足】 CSS1行目~6行目の指定は、全ての要素に共通の指定です。
*{ margin:0; padding:0;}を指定して、デフォルトで出来てしまう余白を削除しています。
こうすることで、以降に指定したmarginが正確に表示されるようになります。
この記事の主旨とそれるので、これ以上詳しくは触れませんが、このコードについてよくわからない方は、この記事の最後に参考記事のリンクを貼っておきますので、そちらをご覧ください。

Sample02:「marginの相殺」が起こっている状態

こちらは、先ほどのSample01に、CSSを一行追加して、box02にmargin-top:40px;を指定しています。
ですが、box01とbox02の間の余白はSample01と変わりありません。
box02に指定したmargin-top:40px;が効いていないのです。

See the Pen sample02 by natsuki (@natsukimemo) on CodePen.

*{
  margin:0;
  padding:0;
}
section{
  width:300px;
  height:100px; 
}
.box01{
  background-color:red;
  margin-bottom:50px;
}
.box02{
  background-color:blue;  
  margin-top:40px; /* ←これを追加 */
}

これは、box01のmargin-bottom:50px(CSS11行目)とbox02のmargin-top:40px(CSS15行目)が上下、つまり縦重なっているため、marginの相殺が起こっています。

Sample03:間に何か入れれば効く

では、box02に指定したmargin-top:40px;を効かせるにはどうしたらいいのでしょうか。
それは、box01とbox02の間になにか挟んで、marginを重ねなければいいのです。

下は、box01とbox02の間にテキストを入れてみました。
marginが重なっていないので、ちゃんとbox02に指定したmargin-top:40pxが効いています。

See the Pen sample03 by natsuki (@natsukimemo) on CodePen.

<div class="box01">
  <p>box01</p>
</div>
text /*←これを追加*/
<div class="box02">
  <p>box02</p>
</div>
スポンサーリンク

親要素と子要素間のmarginについて

親要素と子要素間のmarginでも、縦にmarginが重なれば相殺が起こります。

これについて具体的に見ていく前に、まず子要素にmarginを指定した場合、どういった表示になるのか見てみましょう。
意外と勘違いしている人が多いので、今一度確認です。

子要素のmarginの表れ方

Sample04:子要素にmargin-topを指定した場合

下記は、boxの上に50pxの余白を入れています。

See the Pen sample04 by natsuki (@natsukimemo) on CodePen.

<div class="parent">
  <p class="child">box</p>
</div>

HTMLは、p.childがdiv.parentの入れ子になっています。
div.parentの子要素であるp.childにmargin-top:50pxを指定して、余白を作っています。(下記CSS12行目)

*{
  margin:0;
  padding:0;
  font-size:30px;
  color:green;
}
div.parent{
  width:300px;
  background-color:blue;
}
p.child{
  margin-top:50px;
  background-color:red;
}

このCSSのポイントは、CSS9行目と13行目でdiv.parentとp.childに背景色を指定しているところです。
div.parentには青色を、p.childには赤色の背景色を指定しています。
上の表示を見てみると、div.parentに指定した背景色の青(blue)が全く見えません

つまり、子要素であるp.childにmargin-topを指定すると、指定した子要素とともに親要素の上に余白ができる、ということです。
・・・ちょっと、何言ってるかわかりにくいですね。。。
子要素にmargin-topを指定しても、下のAのようにはならない、ということです。

子要素にmargin-topを指定した場合、親要素の内側に余白ができるわけではありません
Bのように親要素を含めて余白がとられます。
結構これ、勘違いしている人、多くないですか?Aのようになるって思ってませんでした?

では、上のAのように親要素の内側に余白を作りたい場合は、どうすればいいのでしょうか。

Sample05:親要素の内側に子要素のmargin-topで余白を入れるには

こちらは、先ほどのSample04に、CSSを一行追加して、親要素であるdiv.parentにborderを指定しています。
するとp.childのmargin-top:50pxが、div.parentの内側に効いて、div.parentに指定した背景色blueが表れています。

See the Pen sample05 by natsuki (@natsukimemo) on CodePen.

*{
  margin:0;
  padding:0;
  font-size:30px;
  color:green;
}
div.parent{
  width:300px;
  background-color:blue;
  border:3px solid green; /* ←これを追加 */
}
p.child{
  margin-top:50px;
  background-color:red;
}

CSS10行目、div.parentにborderでgreenを指定しました。
それ以外は、Sample04と全く同じです。

このように親要素にborderやpaddingなどを指定すると、親要素の内側で子要素のmargin-topが効くようになります。

ひとつ注意なのは、このborderやpaddingなどは親要素に指定することです。
子要素であるp.childに指定しても、親要素の内側に余白を作ることはできません。

それでは、このような子要素のmarginの表れ方を確認したところで、この記事のテーマ「marginの相殺」に話を戻しましょう。

スポンサーリンク

親要素と子要素間のmarginの相殺

例1. 親要素と子要素のmargin-topが重なった場合

Sample06

下は、親要素にmargin-top:40px;(下記CSS10行目)を、子要素にmargin-top:50px;(下記CSS13行目)を指定しています。
親要素と子要素のmargin-topが重なっているため、相殺が起こっています。
子要素で指定した50px分しか余白が空いていません。

See the Pen sample06 by natsuki (@natsukimemo) on CodePen.

*{
  margin:0;
  padding:0;
  font-size:30px;
  color:green;
}
div.parent{
  width:300px;
  background-color:blue;
  margin-top:40px;
}
p.child{
  margin-top:50px;
  background-color:red;
}

下のように親要素と子要素のmargin-topが重なっているので、marginの相殺が起こっています。

Sample07

では、親要素のmargin-topと子要素のmargin-top、ともに効かせたい場合は、どうすればいいのでしょう。
そうです、Sample05と同じように親要素にborderやpaddingなどを指定します。

See the Pen sample07 by natsuki (@natsukimemo) on CodePen.

*{
  margin:0;
  padding:0;
  font-size:30px;
  color:green;
}
div.parent{
  width:300px;
  background-color:blue;
  margin-top:40px;
  border:3px solid green; /* ←これを追加 */
}
p.child{
  margin-top:50px;
  background-color:red;
}

CSS11行目、親要素div.parentに、borderを指定しました。
他は、Sample06と全く同じです。

表示を見ると、親要素div.parentの背景色である青色が見えています。
これはp.childに指定したmargin-top:50pxが、div.parentの内側で効いたためです。
更によく見てみると、親要素div.parentに指定したmargin-top:40px;が効いて、div.parentの上に40pxの余白ができています。

親要素div.parentにborderを指定したことで「marginの相殺」が起こらなくなりました。

例2. 親要素にmargin-bottom、隣接ブロックの子要素にmargin-topを指定した場合

次に隣接ブロックの親要素と子要素間でのmarginの相殺を見てみましょう。

Sample08:marginの相殺が起こっている場合

こちらは、box01とbox02の間に50pxのmarginがとられています。
これはbox02の子要素に指定したmargin-top:50pxによる空白です。
box01にもmargin-bottom:40pxを指定していますが、相殺されています。

See the Pen sample08 by natsuki (@natsukimemo) on CodePen.

HTMLは、親要素box01、box02ともに、子要素pタグを入れ子にしています。

<div class="box01">
  <p class="box01_child">box01</p>
</div>
<div class="box02">
  <p class="box02_child">box02</p>
</div> 

CSSではbox01にmargin-bottom:40px(下記CSS12行目)を、box02の子要素であるp.box02_childにmargin-top:50px;(下記CSS15行目)を指定しています。

*{
  margin:0;
  padding:0;
  font-size:30px;
  color:green;
}
div{
  width:300px;
  background-color:red;
}
div.box01{
  margin-bottom:40px; 
}
p.box02_child{
  margin-top:50px;
}

このように別のボックスの親要素と子要素間でも、縦のmarginが重なれば、marginの相殺は起こります

Sample09:marginの相殺が起こらないようにする

box02の親要素にborderを指定してみます。

See the Pen sample09 by natsuki (@natsukimemo) on CodePen.

*{
  margin:0;
  padding:0;
  font-size:30px;
  color:green;
}
div{
  width:300px;
  background-color:red;
}
div.box01{
  margin-bottom:40px;   
}
div.box02{
  border:1px solid green; /* ←これを追加 */
}
p.box02_child{  
  margin-top:50px;
}

表示を見ると、親要素div.box02の縦が50px広がって、div.box02の内側に子要素p.box02_childに指定したmargin-top:50pxがとられています。
そして、div.box01とdiv.box02の間にdiv.box01に指定したmargin-bottom:40pxの空白ができています。
marginの相殺が起こっていません。

まとめ

いろいろサンプルを出しましたが、marginの相殺は下記の3つが揃えば、どこでだって起こる現象です。

marginの相殺がおこる3つの条件

  • 「ブロックレベル要素」
  • 「縦」
  • 「marginが重なる」

この3つがそろうと、marginの相殺がおこる

まあ、「marginが重なる」、なんてことは全体を把握して、計画的にCSSを記述していけば、やらないことなんでしょうが・・・
けど、なかなかCSSを計画的に綺麗に書くって、難しいんですよねーーーー。
本当、いつも苦労しています。。。

この記事がお役に立てるものになっていると嬉しいです。

途中、補足を入れました「*{margin:0;padding:0;}」については下記の記事が参考になると思います。 よければご覧ください。

marginが効かない例については、下記の記事も書いています。

スポンサーリンク
スポンサーリンク
スポンサーリンク
スポンサーリンク
おすすめの本