CSS 盒子的邊距塌陷

雲叔_又拍雲發表於2021-11-02

tip:為能更直觀地學習,本文章已省略部分 css 樣式程式碼。

我相信下面的情形大家在日常工作中常常碰到:在製作靜態頁面中,為了頁面整體的協調與美觀,我們想讓子盒子 image-div 的上邊沿距離父盒子 header-div 的上邊沿有一定間距。

現頁面效果:

目標頁面效果:

為了達成上圖的效果,我們首先就能想到給子盒子設定一個上外邊距:

<style>
    .image-div {    /*子盒子*/
        margin-top:25px;
    }
</style>

讓我們來看看結果如何呢?

結果和我們所預料的並不相同,子盒子 image-div 並沒有和父盒子 header-div 的上邊沿形成一定的間距。這兩個盒子竟然一起往下移動了,多出了紅框區域。

而這種現象,就是 CSS 中常遇到的“邊距塌陷”問題中的一種。

邊距塌陷

流內塊級元素的 top 與 bottom 外邊距有時會合並(塌陷)為單個外邊距(合併後最大的外邊距),這樣的現象稱之為外邊距塌陷(margin collapsing)。

導致邊距塌陷的原因是外邊距,有以下四種情況計算情況:

  • 如果都是正數,則取最大值

  • 如果相同,則取其中之一

  • 如果有正有負,則取最大的正數加上最小的負數之和

  • 如果都是負數,則取最小值。

相鄰(兄弟)盒子之間的塌陷

在 CSS 當中,相鄰兩個兄弟盒子的外邊距區域是公共的,這會導致相鄰兄弟盒子之間的邊距出現塌陷情況。

下圖是相關示例,設定div1盒子的下邊距,另設定下方 div2 盒子的上邊距:

<style>
    #block1 {
        margin-bottom: 20;
    }
    #block2 {
        margin-top: 10;
    }
</style>

<div id = "block1">div1</div>
<div id = "block2">div2</div>

在瀏覽器開發者工具先看 div1 的 margin 區域(紅框):

div2 的 margin 區域(綠框區域):

對應情況:兩個盒子之間的外邊距如果都是正數,則取最大值。

下方為示例 2,我們將示例 1 中的外邊距改為負數:

<style>
#block1 {
    margin-bottom: -20;
}
#block2 {
    margin-top: -10;
}
</style>

<div id = "block1">div1</div>
<div id = "block2">div2</div>

兩個盒子的重疊距離為兩個負數中最小的數“-20px”(絕對值最大 |-20px|)。

解決方法

如果想要避免這種塌陷,可以通過下面兩種方法解決:

  • 只給其中一個盒子設定外邊距

  • 給兩個盒子分別套一個父盒子,父盒子屬性設定為 overflow:hidden,同時讓父盒子是密閉區域,從而觸發 BFC

父子盒子之間的塌陷

然而設定父盒子也不是萬全的,當出現以下情況時外邊距會塌陷:

  • 塊元素 的 margin-top 與 它的第一個子元素 的 margin-top 之間沒有 border、padding、inline content、clearance 來分隔。

  • 塊元素 的 margin-bottom 與 它的最後一個子元素 的 margin-bottom 之間沒有 border、padding、inline content、height、min-height、max-height 分隔。

同時,如果父子公用一段上邊距區域,比如父盒子沒有上邊距時,子盒子設上邊距。這時子盒子帶著父盒子向下移動(相當於給父盒子設定外邊距)就會產生盒子塌陷。


<style>
*{
    margin:0px;
    padding: 0px;
}
.div1{
    width:300px;
    height: 200px;
    background-color: cornflowerblue;
    margin:0px;
}
.div2{
    background-color: wheat;
    margin: 30px;
}
</style>

<div class="div1">
    <div class="div2">
        div2             
    </div>
</div>

父元素不設定外邊距,第一個子元素設定 margin:30px,會發現父元素與子元素一起往下移動了 30px:

解決方法

想要解決這種塌陷的核心辦法是把父子盒子分隔開。我們可以給父盒子設定邊框或者內邊距,或者給父盒子標籤新增 overflow:hidden 屬性,通過觸發 BFC 規則,也就是塊級格式上下文,把父級渲染成一個獨立區域,從而解決父子盒子之間的塌陷問題。

BFC 規則觸發方式:

  • float 不為 none

  • overflow 不為 visible(常用 overflow:hidden)

  • position 為 fixed,absolute

  • display 為 flex,inline-block,table-cell

當然,在選擇塌陷的解決方案時,應依據具體的情境,不能所有情況都使用相同的方案,否則會造成其他問題的出現哦~

那麼,在我們學習以上知識後,就能清晰地知道開頭引入的問題正是父子盒子間的塌陷,我們可以通過觸發 BFC 規則(僅其中一種方案)來解決:

<style>
    .image-div {    /*子盒子*/
        margin-top:25px;
    }
    .header-div {   /*父盒子*/
        overflow:hidden;    /*觸發bfc*/
    }
<style>

以上就是 CSS 盒子邊距常見的塌陷與解決辦法,希望能夠對你有所幫助。

推薦閱讀

一文讀懂瀏覽器儲存與快取機制

Python Type Hints 從入門到實踐

相關文章