CSSで要素の余白を表すmarginとpaddingについて正しく理解する

要素の余白を決定するmarginとpadding

CSSには要素の余白を表すプロパティとしてmarginpaddingが用意されています。この二つのプロパティは、ボックス・モデルにおいて固有の範囲を持ち、専用の面積を作り出すことができます。

marginは要素の外側の余白を表し、paddingは要素の内側の余白を表します。これらの間には、境界線であるborderが挟まれています。この全てが、内容を配置するコンテンツ・ボックスを取り囲んでおり、寸法を広げると外側へ向かって拡大します。

本来、widthheightは純粋に内容が配置されるコンテンツ・ボックスの寸法を表します。これを理解しないままレイアウトを行うと、想定したサイズに合わなかった要素が、親要素からはみ出したり崩れた状態で表示されます。

また、垂直方向の余白は状況に応じて折りたたまれることがあるため、指定したmarginが期待したように反映されないということが起こります。それを防ぐために、CSSの余白を正しく理解しておく必要があるのです。

内側の余白であるpaddingの正しい解釈

まずは、内側の余白を定義する「パディング」について見て行きましょう。paddingは、CSSのボックス・モデルを構成する区域のうち、パディング・ボックスの寸法を指定するプロパティです。

パディング・ボックスは、専有の面積を持つ固有の区域で、コンテンツ・ボックスとボーダー・ボックスの間に隣接しています。これはどういうことかと言うと、境界線の内側にあるため、ボックスの内側に属しているということです。例えば、凡庸な<div>要素で囲んだテキストを配置した場合、パディングは<div>の内部構造の一部です。

要素の内部に含まれている以上、paddingは外部環境の影響を受けません。例え内容が空の要素であっても、paddingを指定すれば折りたたまれずにそのまま表示されます。

以下の例は、要素のサイズ変更と余白の関係を可視化したものです。要素のwidthheightの値を変更すると、ボックスの寸法が変化します。背景色はbackground-clipの機能を使ってコンテンツ・ボックスのみに適用しているため、余白の部分は親要素に指定されている青色を透過します。

上記の例では、paddingの値を増加させると余白の寸法が外側へ向かって拡大します。これはbox-sizingの値が既定値のcontent-boxになっているためです。この状態の要素は、標準モデルの計算値でレイアウトされます。この時、widthheightで示される寸法は、コンテンツ・ボックスの大きさを表します。

box-sizingの値をborder-boxに変更すると、代替モデルでの表示に切り替わります。この状態の要素は、内部構造に含まれるpaddingborderを内側へ向かって拡大します。つまり、コンテツ・ボックスは圧迫され、幅や高さが足りない場合に押しつぶされて見えなくなります。

外側の余白であるmarginの正しい解釈

続いて、外側の余白を定義する「マージン」について見て行きましょう。marginは、CSSのボックス・モデルを構成する区域のうち、マージン・ボックスの寸法を指定するプロパティです。

マージン・ボックスは、専有の面積を持つ固有の区域で、ボーダー・ボックスの外側を取り巻いています。これはどういうことかと言うと、境界線の外側にあるため、ボックスの外側に属しているということです。例えば、凡庸な<div>要素で囲んだテキストを配置した場合、マージンは唯一外部環境に触れている部分です。

要素の外部環境に触れているということは、当然その影響を受ける可能性があるということです。例えば、値の異なる垂直方向のマージンがぶつかった場合に、最大値を持つ方が優先されて少ない値が吸収されます。この機能はマージンが相殺されることから、折りたたみ(collapsed)とも呼ばれます。

以下の例では、隣接する要素に指定されたマージンが相殺される様子を確認できます。ここでのしきい値は30pxです。それを下回る数値では、隣接するマージンに余白の寸法が吸収されます。

上記の例では、同じ階層に所属する要素同士の関係でしたが、親要素に対する子要素の挙動にも影響します。例えば、包含ボックスの直下にブロック要素を配置して、垂直方向のマージンを指定した場合、この余白は包含ボックスを貫通します。

次の例は、<div>要素を入れ子にした状態で、子要素にmarginを追加した場合の挙動です。本来であれば、上下左右の全方向にマージンが適用されて、包含ボックスの背景を映したいのですが、左右が適用される反面、上下方向のマージンは効いていないように見えます。しかし、隣接するボックスとの余白が広がります。これは親要素を貫通して外側の空間に影響を及ぼしていることを意味します。

この現象を回避するためには、一種の衝突材が必要になります。具体的に言うと、子要素のマージンとぶつかるような素材を親要素に置いてあげれば良いのです。一番簡単な方法としてはテキストを配置するだけで、それが衝突判定の材料になります。

上下のマージンが効かない場合の対処方

包含ボックスの中に配置した子要素の垂直方向のマージンが効かない場合、CSSを用いた解決方法は何らかのプロパティを親要素に追加することです。その効果があるものを見ていきましょう。


<div id="container">
	<section>
		<h1>何も指定しない</h1>
		<div>
			<div class="item">Item</div>
		</div>
	</section>
	<section>
		<h1>overflow: auto;</h1>
		<div id="wrapper_overflow">
			<div class="item">Item</div>
		</div>
	</section>
	<section>
		<h1>padding: 0.1px;</h1>
		<div id="wrapper_padding">
			<div class="item">Item</div>
		</div>
	</section>
	<section>
		<h1>border: 1px solid transparent;</h1>
		<div id="wrapper_border">
			<div class="item">Item</div>
		</div>
	</section>
</div>
#container {
	overflow: auto;
	padding: 0 1rem 1rem;
	background-color: #eee;
}
#container > section {
	overflow: auto;
	margin: 1rem 0 0;
	padding: 0 1rem 1rem;
	background-color: #fff;
}
section > h1 {
	margin: .5rem 0 0;
	font-size: 1rem;
}
section > div {
	background-color: #f09;
}
div > .item {
	margin: 1rem;
	background-color: #ffc;
}
#wrapper_overflow {
	overflow: auto;
}
#wrapper_padding {
	padding: 0.1px;
}
#wrapper_border {
	border: 1px solid transparent;
}

overflowの効果

包含ボックスにoverflowを追加すると、子要素のマージンが貫通しなくなります。その理由は既定値のvisibleにあります。

overflowを省略した場合、ブラウザは既定値を適用します。この状態で表示された要素は、コンテンツ・エリアからはみ出す内容を、そのまま表示します。つまり、要素の寸法からはみ出したコンテンツをボックスの外へ露出させます。

その結果、親要素のボックスを貫通したマージンが隣接する要素を押して余白が生まれたのです。あくまで、マージンが効いていないのではなく、親要素のoverflowが正しく機能した結果です。

これを回避するためには、overflowの値をvisible以外のものにします。ここではautoを採用していますが、これにより子要素のマージンも包含ボックスの中に含まれるようになります。

paddingの効果

paddingは、パディングの解説で示した通りボックスの内部構造の一部です。そのため、包含ボックスに有効な寸法のパディングを指定すれば、それが子要素のマージンの衝突材料になります。

パディングを省略した場合に既定値で0になっている要素、あるいはCSSリセットで対象となる要素のパディングを0にしている場合は、パディング自体が存在しないことになり、衝突せずにすり抜けが発生します。

ここで注意点があります。例え人間が認識できないほどの小さい数値であっても、厳密なレイアウトには影響を及ぼします。paddingは負の数値を扱えないため、これを有効にするには0以上の寸法を指定する必要があります。

borderの効果

borderを指定すると、当然ながら衝突判定となってマージンの貫通を食い止めます。ですが、境界線に太さを指定するということは、もちろん見た目やレイアウトに影響します。

サンプルでは境界線の色を透明にしていますが、ボーダーの寸法がボックスのサイズに影響を与えています。その装飾がコンテンツに必要なものであれば良いのですが、単にマージンの貫通を避ける目的のためだけに使うことは推奨できません。

borderは、省略された時に既定値でborder-stylenoneが採用されるため、この問題が起こります。ただし、先に示した通り代替案が複数用意されているので、無理に使う必要はないでしょう。

CSSリファレンス一覧