【初心者エンジニア必読】CSSでのmarginの相殺はなぜ、どのように起こるのか?

  • ブックマーク
  • -
    コピー
大将命様

この記事を読む前提条件として、CSSボックスモデルとCSSセレクターを理解していると読みやすいと思います!

 CSSをいじる際、空白の調整は必ず誰もが経験をしたことがあるでしょう。
 デザインにおいて隣り合わせるboxと、どのような空白、あるいは距離感を保つのが最も美しいのか、ということ議論は人々をPC画面に張り付かせ、何時間も悩ませます。

人を感情的に惹きつけるデザインとは?

 相殺の可能性を秘めているマージンは、垂直方向(上下)だけです。水平方向(左右)のマージンは崩壊しません。

マージンの相殺とはなんでしょうか?

 隣り合わせる要素が両方marginを持っている場合、つまり、2つが衝突するとき、1つだけが生き残ります。二つのmarginが重なり合うと、marginの数値が大きい方が勝ち残るんですね。
 具体例を見ていきましょう。

 上の図で、要素Aの下部marginは10pxです。 要素Bの上部marginは30pxです。 要素Bのmargin 30pxの方が、要素Aのmargin 10pxよりも大きいため、2つの要素間のmarginは30pxになりますここ、それぞれのmarginが合計されて40pxとはなりません!(注:要素Aと要素Bのmarginが同じである場合、たとえばそれぞれ30pxの場合、結果のmarginは30pxになります)。

なぜmarginは相殺するのか?

大将命様

なんでこんなことになるんだ!!!

 実際、marginが合計された方が直感的ですよね? なんでこんなややこしいことが起こるのでしょうか? この不気味な仕組みには理由があるのです。

 marginの相殺は、コンテンツのsetの垂直marginを簡単に定義できるように設計されています。

 例を見てみましょう。

 ブログの投稿のように、段落がたくさんあるドキュメントがあるとします。 投稿には、段落以外のコンテンツ(画像、見出し、表など)が含まれていますね。そのコンテンツはすべて、読みやすいように間隔を空ける必要があります。 段落、画像、見出しなどの間に一貫した間隔が必要なのです。
 段落間の間隔を一定にするためには、CSSを定義すると、例えば次のようになります。

p {
margin-top: 12px;
}

 これを、すべての段落の上の空白が12px幅になります。つまり、上の要素と12px分の幅ができるわけですね。ただし、これは上部の余白のみを設定しているため、下のコンテンツとの余白はありません。

 段落要素の下部に12pxのmarginを持たせたい場合は、別途CSSを定義する必要があります。
 しかし、各段落にmargin-topが12px、margin-bottomが12pxになるように設定することはできないのです。なぜなら、これらの余白を組み合わせると、段落間に24pxの余白ができてしまいます。ここまで理解できますか?

大将命様

つまり、崩壊する……

p {
margin-top: 12px;
margin-bottom: 12px;
}

 この場合、各段落(p要素)の間の余白は12pxになります。

margin相殺のルール

 次にmargin相殺のルールを理解していきましょう。

  1. 基本的な概念と主なルールの理解しよう!
  2. 例外の存在を知ろう!
  3. 何かをしたときに、思ったとおりに機能しない場合は、例外が発生している。仕様を参照しよう!

基本的な考え方

  1. marginの相殺は垂直方向にのみ発生します。
  2. これはブロック要素にのみ発生します。つまり、インライン要素では起こらない。
  3. 要素が互いに直接接触している場合にのみ発生します(padding、border、lineboxesなどで区切ることはできません。また、異なる書式設定コンテキストの場合も起こりません)。
  4. CSS仕様はあまりにも膨大なので、すべてを知る必要はありません。高レベルの概念と一般的なルールを学び、必要なときに物事を調べて対応してください。

 CSSは基本的に視覚的であり、marginがどのように相殺するかを確認できます。これらのグラフィックは非常に貴重なので、何が起こっているのかを一回自分自身で確認してみると理解が深まると思います。

大将命様

Janathan Harrellさんのサイトはわかりやすいので、一度読んでみてください!

 なんとなく理解ができてきたところで、一回あなたの頭の中を混乱させてもいいですか?

div {
      margin: 0;
      padding: 0;
    }
    
    p {
      margin: 10px 0;
    } // HTML

  <div>
    <p>Some example text.</p>
  </div>
大将命様

これ、どうなるか想像できる?

 このコードを見ると、段落の上部marginは10pxであると思われるかもしれません。

(引用:https://medium.com/@joseph0crick/margin-collapse-in-css-what-why-and-how-328c10e37ca0

 だがしかし!!!!!

 これが真実です。

 さて、上記のように、paddingやborderのない2つの隣接する要素がある場合、またはそれらの間に何かがある場合(つまり、それらのmarginが垂直に接触している場合)、2つのmarginの大きい方が優先されるという説明はしましたね? ここ怪しい人は、もう一回最初から読め!
 しかし、今回の場合、要素は親と子の関係にあります。ここでの「ロジック」はちょっとトリッキーです。

  • 親のmarginは0pxです。
  • 子には10pxのmarginがあります。
  • 10pxは0pxより大きいので……
  • 親divは10pxのmarginを取得します。
大将命様

理にかなってるでしょ?

まとめ

 marginの相殺は少し複雑です。とはいえ、marginの相殺はよく起こります。それが何であるか、いつ起こるか、そしてそれをどのように扱うことができるかを理解するということは、CSSを習得する上で基本なので、ぜひこの際に学んでおいていただきたかったので、この記事を書きました。

 もっと知りたい!という人は、SUNABACOプログラミングスクールにまず話だけでも聞いてください!スクール料金も5万円〜と超お得です!

  • ブックマーク
  • -
    コピー

この記事を書いた人

大将

大将

エストニアの国立大学、タリン工科大学在学中に現地案内事業で起業。大学院では文学の数値解析の研究と小型人工衛星研究開発チームに所属。データサイエンティストとしてさまざまなプロジェクトに関わり、現在はフロントエンドの開発やVR教育やVR美術館などの創作や事業を行っている。元テニスコーチ。