iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 6
2
自我挑戰組

前端新手進化史系列 第 6

Collapsing margins

文章將陸續整理並更新至個人部落格


一、什麼是 Collapsing margins?

先來看一段 W3C 規範 的敘述:

In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.

簡單來說,當相鄰(adjoining)的 margin 相遇時,若合併成一個 margin,這種情況稱為 Collapsing margins。其中,W3C 對於相鄰(adjoining)的定義為:

  • 僅發生於垂直方向

  • 皆為在文檔流中(in flow)的塊級元素(block-level)元素,且參與同一個塊格式化上下文(block formatting context,BFC)

    例如,若是元素會創建新的 BFC,像是根元素 <html> 、float、position: absolute......等等,該元素就不會有 margin collapsing,至於什麼情況下會創建新的 BFC,可參考 MDN-block formatting context

二、什麼時候會發生 margin collapsing?

margin collapsing 可分為兩種情況,一種是同層元素之間,另一種是元素與其父(母)容器之間,但並非所有 block-level 元素皆會發生 margin collapsing,而是有前提條件的。

(一) 相鄰的兄弟姊妹

同層且相鄰的 block 元素的 margin-bottom 與 margin-top 相遇時,發生重疊,僅發生於垂直方向。

前提條件:

block 須符合相鄰(adjoining)的定義:

例如:兩個相鄰的 block 元素,紅色 block 的 margin-bottom = 30px,黑色 block 的 margin-top = 30px,最終兩個 block 元素之間的距離為 30px,而非 60px。

(二) 容器與其第一個/最後一個子元素

亦僅發生於垂直方向,且有其前提條件。

前提條件:

  • 皆為在文檔流中(in flow)的塊級元素(block-level)元素,且參與同一個塊格式化上下文(BFC)

  • 容器設定邊框(border)內距(padding)或加上 clear-fix 的屬性。

例如:

虛線為容器的 outline,紅色區塊為容器內的第一個子元素,現在子元素頂部緊貼著容器頂部。若想利用 margin-top 屬性,讓子元素的頂部距離容器頂部 50px。
結果會發現,子元素的頂部並沒有與容器頂部分離!

<div class="container">
    <div class="first_child">容器中的第一個子元素</div>
</div>
.first_child {
    margin-top: 50px;
}

打開開發人員工具檢視一下,會發現子元素的 margin-top 竟然跑出容器外了,這結果會與直接在容器上設定 margin-top: 50px 是一樣的

解決方法:

使其不再符合前提條件,例如不再是 block、加上 border 或是創建 BFC。


三、margin 計算方式

當發生 margin collapsing 時,由於外距(margin)可為負數,故會有三種情況:

  • 兩個 margin 皆為正 ⇒ 取大值

  • 一個 margin 為正,一個 margin 為負 ⇒ 相加

  • 兩個 margin 皆為負 ⇒ 取最小 (最負)



參考資料

  1. W3C - Collapsing Margins
  2. W3C - Box Model
  3. MDN - Mastering margin collapsing
  4. MDN - Block formatting context

上一篇
基礎 box model (下)
下一篇
混血兒 inline-block
系列文
前端新手進化史30

尚未有邦友留言

立即登入留言