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が効かない例については、下記の記事も書いています。
【番外】WEB制作におすすめの本
【番外】パソコン時短技
知ってるか知らないかだけで作業スピードが全く違うので読んで損のない本。