この記事の目次
下のmarginを24px、次の要素の上を16pxにしたのに、間隔が40pxにならない。上下のマージンが相殺される場面では、指定値を増やす前に、どの要素同士の余白が接しているかを調べます。
HTMLの親子関係とCSSのクラスが読める人向けに、架空の植物交換会の案内欄を作ります。エディターとブラウザーを用意してください。通常の横書きのブロック配置に絞り、負のmarginや空のブロックが連続する場合は扱いません。
24と16が、40になるとは限らない
通常の流れで上下に隣接するブロックでは、下側と上側のmarginが相殺される場合があります。この練習のように両方が正の値なら、足し算ではなく大きい側の値が使われます。24pxと16pxなら24pxです。
MDNのマージンの相殺は、隣り合う兄弟だけでなく、境界のない親子でも起きることを説明しています。「marginはいつでも大きい方になる」と覚えるのは広すぎます。左右の余白やFlexboxの項目間に、この計算をそのまま持ち込まないでください。
まず対象の背景に色を付け、要素の端と余白を区別します。文字の見た目の上端は、行の高さによって箱の上端と一致しないことがあります。数値を調べるときは、文字間の空きではなく、開発者ツールで要素の箱の端を追います。
二つの段落で、兄弟間の相殺を再現する
次をmargin-practice.htmlへ保存し、ブラウザーで開きます。上側は兄弟、下側は親子を比べるための見本です。周囲の枠や見出しに実験が広がらないよう、見本を囲むdemoにpaddingを付けています。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>上下の余白の練習</title>
<style>
body { margin: 1rem; font-family: sans-serif; line-height: 1.8; }
main { max-width: 36rem; margin-inline: auto; }
.demo { padding: 1px 0; }
.first { margin: 0 0 24px; background: #fff0dd; }
.second { margin: 16px 0 0; background: #dceef5; }
.panel { margin: 0; background: #fff0dd; }
.panel h2 { margin: 24px 0 0; }
.panel p { margin: 0; }
</style>
</head>
<body>
<main>
<h1>植物交換会(架空の練習)</h1>
<section class="demo" aria-label="兄弟の余白">
<p class="first">苗の受付は入口です。</p>
<p class="second">交換は奥の机で行います。</p>
</section>
<section class="demo" aria-label="親子の余白">
<div class="panel"><h2>持ち物</h2><p>持ち帰り用の袋をご用意ください。</p></div>
</section>
</main>
</body>
</html>
firstの背景の下端とsecondの背景の上端を測ると、間は24pxになります。secondの上marginを8pxへ変えても間隔は24pxのままです。逆に32pxへ変えれば32pxになります。同じ場所の一つの値だけを変え、どちらの指定が大きいかと照合してください。
ここで40pxにしたいなら、下marginを40px、次の上marginを0にするなど、一方へ間隔の責任を寄せられます。意図した間隔が24pxなら、すでに誤りとは限りません。相殺をすべて止めることではなく、指定の理由を説明できることを目指します。
子の上余白が背景の外へ出たら、親子を調べる
下のpanelでは、h2の上marginが親と相殺し、背景の内側に24pxの空きができません。見出しへmarginを足したのに、親全体の位置が動いたように見えるのが一つ目の失敗です。背景はmargin部分を塗らないため、背景の外に空きが残ります。
「持ち物」の上に色付きの余白を作りたいなら、親へpadding-top: 24pxを付け、h2のmargin-topを0に変更します。余白を背景の内側に持たせる意図と、CSSの担当が一致します。再確認では、panelの上端から見出しの箱の上端まで24pxの背景が見えるかを調べます。
別の実験として、元のh2のmarginを残し、panelにdisplay: flow-rootだけを加えると、親子の相殺を防げます。MDNのdisplayでflow-rootの説明を確認できます。ただしこれは内側余白を指定する値ではありません。子のmarginを変更すれば空きも変わります。
最終版ではpaddingの案を採用します。子の見出しを別のものへ差し替えても、案内欄の内側余白は親の規則として残したいからです。理由なくoverflow: hiddenを足して止めると、別のはみ出しまで隠すことがあるため、この課題の解決に使いません。
親を直しても、兄弟の余白が足し算になるわけではない
二つ目の失敗は、兄弟を囲むdemoにflow-rootを付け、24pxと16pxの間隔が40pxになると期待することです。親と子の相殺を防ぐことと、内部の兄弟同士の相殺をなくすことは別です。期待した変化がないからと、同じ指定を子へ何度も足さないようにします。
修正では、兄弟間の間隔を一方のmarginにまとめます。連続する部品を一定間隔で並べたいなら、親をGridなどの配置へ変えてgapを使う別案もあります。ただし配置の仕組みも変えるので、記事本文の段落へ無条件に適用する方法にはしません。
再確認は、親子の見本を変更しても、上の二段落は24pxのままであることです。次にfirstの下marginだけを40px、secondの上marginを0にして、40pxへ変わることを確かめます。問題の組を分けると、何を直した結果かが明確になります。
余白の担当を決めてから、値をそろえる
box-sizingの解説は、幅へpaddingとborderを含める計算を扱っています。border-boxへ変えても、今回の兄弟間の相殺は解消しません。幅の計算と、上下の余白の接し方を同じ問題にしないことが大切です。
また、gapによる項目間隔は並べる親へ間隔を持たせる設計です。既存の段落の見た目が想定と違うときは、まず現在の配置で原因を再現してから、そのままmarginで直すか、並べ方を変えるかを選びます。
兄弟の40pxと親の24pxを、別々に測る
見本を保存し、最終版は兄弟の間隔40px、親の内側余白24pxへ直します。次の条件を、変更したセレクターと一緒に記録してください。
- 初期状態で24pxと16pxの兄弟間隔は24pxになる。
- secondを8pxへ変えても24px、32pxへ変えると32pxになる。
- 最終版はfirstが40px、secondが0で、間隔は40pxになる。
- panelのpadding-topが24px、h2の上marginが0で、内側に背景付きの空きができる。
幅を320pxへ狭めて文章が折り返しても、箱の端から測った間隔が維持されるかも見ます。レスポンシブCSSの無料レッスンで配置を変える前に、兄弟と親子のどちらを直す課題だったかを一文にできれば完成です。
記載内容へのご質問や訂正のご連絡は、hello@junkbranding.comまでお願いします。