CSS Box Model 盒子模型是 CSS 的基礎。我們可以簡單的理解為, html 元素在 CSS 裡面,都可以視為一個一個的盒子(Box)。
如下圖,Box Model 由四個主要的部分來組成,由內而外分別是:
我們可以藉由「網頁開發者工具」來觀察網頁上的 Box:
今天我們要來討論的主角是 margin(外邊距)
。
margin 是 box model 的外邊距,我們非常常使用這樣的屬性,例如相鄰的兩個元素我們希望他們之間能夠有一些間隔,我們就能夠使用 margin 來實現:
.container {
display: flex;
}
.block {
width: 200px;
height: 200px;
}
.ml-20 {
margin-left: 20px;
}
<div class="container">
<div class="block"></div>
<div class="block ml-20"></div>
<div class="block ml-20"></div>
</div>
但在使用 Margin 的時候,我們會需要特別留意「邊距重疊」的問題,因為若忽略這個問題,我們會在不預期的時候,發現不知道為什麼 Margin 的設定失效了。
以 MDN 的定義:
當一個 Block 的下邊距範圍(margin-bottom)和一個 Block 的上邊距範圍(margin-top)都有設定時只會留下最大那個,這種情況我們稱為邊距重疊 (margin collapsing)。請留意設定了 float 或絕對定位的元件並不會產生邊距重疊。
以下面為例,同一父層的兩個相鄰的 block,上下邊距會重疊。因此兩個 block 之間的距離就不會是預期的 40px,而是 20px。當兩個 block 的 margin 不同時,會取大的那一個。
.mb-20 {
margin-bottom: 20px;
}
.mt-20 {
margin-top: 20px;
}
<div class="container">
<div class="block mb-20"></div>
<div class="block mt-20"></div>
</div>
其中一個解決方案是,當父元件不使用 block model 時,就不會產生邊距重疊:
.container {
display: flex;
flex-direction: column;
}
根據上述描述,「同一層相鄰的 Block,上下邊距會造成重疊」,所以如果我們讓原本相鄰的元素中間插入一個「空元件」,就不會重疊了吧?
但答案是,還是會造成重疊!
雖然兩個元素沒有相鄰,但因為空的元件導致他們實質上是相鄰的,所以會跟第一個上下相鄰元件是有一樣的問題。
.mb-20 {
margin-bottom: 20px;
}
.mt-20 {
margin-top: 20px;
}
<div class="container">
<div class="block mb-20"></div>
<div></div> /* 空元件 */
<div class="block mt-20"></div>
</div>
以下面這個情境為例,當父元件與第一個子元件同時都有 margin-top
時,並且父元件沒有設置 border, padding, overflow 時,父元件的 margin-top
會和其第一個子元件的 margin-top
重疊:
.mt {
margin-top: 20px;
}
<div class="container mt-20">
<div class="block mt-20"></div>
</div>
因此,解決方法可以考慮下面幾個:
今天介紹的「邊距重疊」問題是很經典也很常見的問題,但因為是個小細節,通常問題會被淹沒在很多複雜的 CSS 樣式裡面,所以也有可能很難被發現。並且因為邊距重疊的出現也會有一些條件,有時候有,有時候沒有,因此對邊距重疊規則的掌握很重要,他能夠幫助我們快速發現問題並解決。