marginプロパティの謎仕様について解説します
2023.02.20
CSSの勉強を進めていくと、margin
プロパティの挙動に疑問を抱く瞬間があると思います。
もしも疑問を抱いていないのであれば、まだまだ学習が足りていないか、とんでもなく優秀な人かもしれません。
一見すると謎仕様ですが、キチンとした理由が存在しています。
ここで紹介する謎仕様を理解しておくと、間違った修正を施す失敗を防ぐことができます。
CSSの仕様は奥が深く、複雑なものが多いのですが、頻度の高いものや広く周知されているものについては、しっかりと理解しておく必要があります。
今回は、margin
プロパティにスポットを当てて、謎仕様と思われるものについて紹介していきたいと思います。
目次
隣接要素でmarginが相殺される
隣接する要素(ボックスコンテンツに限ります)で上下のmargin
を設定すると、上部にあるコンテンツの下余白と下部コンテンツの上余白が重なり合って相殺されてしまいます。
左右の余白では、右余白20px、左余白30pxとした場合は、重ならずに50pxの余白として設定されます。
以下の事例では、下余白20px、上余白50pxとした場合、相殺されて50pxの余白として設定されるようになっています。
事例
<div id="cont01">
<p>テキストテキストテキスト</p>
</div>
<div id="cont02">
<p>テキストテキストテキスト</p>
</div>
#cont01 {
margin-bottom: 20px;
}
#cont02 {
margin-top: 50px;
}
テキストテキストテキスト(↓ margin-bottom: 20px)
テキストテキストテキスト(↑ margin-top: 50px)
原因・対策
なぜこのようにmargin
の相殺が発生するかというと、HTML上のコンテンツ(ボックスコンテンツ)は基本的に上から下に並んで表示されます。
意図的に横に並べることはありますが、特に指定しなければボックスコンテンツは上下に並んで表示されます。
そのため、上下の余白に対して誤って指定した場合でも均一に表現できるようにと、上下の余白を相殺して大きい余白の方を生かすような仕様になっています。
対策としては、重なり合う下余白と上余白の間に何かしらのコンテンツを挟むという方法があります。
高さゼロの空要素を挟むことで、上記の例の場合は70pxの余白を獲得することができます。
もっとも一番正しい対処としては、下余白か上余白かどちらかに統一して指定するのが正解のような気がします。
子要素のmarginが親要素に設定される
親要素と子要素の間に余白を設定しようとして子要素にmargin
を設定した場合、親要素の外側に余白が設定されてしまうことがあります。
厳密には、親要素内の先頭の子要素に対するmargin-top
、最後の子要素に対するmargin-bottom
について親要素のmargin
と相殺されるという仕様になっています。
事例
<div id="cont03">
<p>テキストテキストテキスト</p>
</div>
#cont03 {
background: #cff;
}
#cont03 p {
width: 75%;
margin: 30px auto;
background: #fcf;
}
テキストテキストテキスト(↑ margin-top: 30px)
原因・対策
原因というか仕組みとしては、上記の上下余白が相殺されるものと同じで、この例では親要素の上余白と子要素の上余白が相殺されています。
margin
は、隣接要素の間に余白を設定するために使用されるのが一般的な使い方となっているので、対策として親要素と子要素の間に余白を設定する場合には、padding
を使うのがスマートな方法になります。
floatと混在するとmargin: auto;が効かない
float
プロパティを設定した状態のボックスコンテンツに、margin: auto;
を設定してもブラウザの中央に表示されません。
float
が設定された要素は、3Dのように画面の前面に浮き上がるイメージで配置されます。
したがって、float
の設定がない要素とある要素同士の余白設定は干渉しないため、結果としてfloat
の設定された要素にmargin: auto;
を設定しても余白が適切に反映されません。
事例
<div id="cont04">
<p>テキストテキストテキスト</p>
</div>
#cont04 {
width: 50%;
float: left;
margin: auto;
}
テキストテキストテキスト
原因・対策
前述したとおり、float
を使用するとボックスコンテンツが前面に浮き上がった状態になり、left
またはright
に配置されます。
浮き上がったボックスコンテンツのmargin
は、そうではないボックスコンテンツに対して影響を与えません。(※ボックスコンテンツの内容に対しては影響を与えます)
したがって、float
を使用しているコンテンツにmargin: auto;
を設定してもブラウザの中央には配置されないという結果になります。
ブラウザの中央にコンテンツを配置するのが目的であれば、float
の設定を削除します。
float
でコンテンツを重ねて表示させるのが目的であれば、margin: auto;
を削除します。
両方を生かす(コンテンツを重ねて、且つブラウザの中央に配置する)には、
- positionプロパティを使う
- 中央に配置したいコンテンツをinline-blockにする
- flexboxを使う
などの方法があります。
これらの詳しい対処方法は、またどこかで紹介できればと思います。
まとめ
marginプロパティの機能としては、ボックスコンテンツにに対して外側に余白を設定するという単純なものですが、隣接する要素(ボックスコンテンツ)同士の間に余白を設定するという側面もあるので、その辺りをキチンと把握しておかないと、思いがけずおかしな挙動のように見える場合があります。
- 隣接要素同士の余白が相殺される
- 子要素の余白が親要素に反映される
- floatと混在するとmarginが効かない
などの現象は、一見すると不具合のような挙動ですが、すべてmarginプロパティの仕様として正しいものになっています。
仕様を正しく理解することで、正しい対処の仕方も一緒に身につけていきましょう!!