CSS外邊距合併&塊格式上下文

前言

以前在前端開發的過程當中,都沒有遇到外邊距合併的問題(實際上是由於大多時候都直接用前端樣式庫(〃'▽'〃)),這一次須要動手排一個頁面,也挺簡單,可是遇到了一個奇怪的問題,因此學習記錄一下。html

問題

測試代碼以下:前端

<!doctype html>
<html class="no-js" lang="">

<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>test</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<style>
* {
    margin: 0;
    padding: 0;
}

body {
    max-width: 750px;
    margin: 0 auto;
}

.div1 {
    background: yellow;
    height: 200px;
}

.div2 {
    background: blue;
    height: 200px;
}

.div2Child {
    background: red;
    height: 100px;
}
</style>

<body>
    <div class="div1">我是吃瓜羣衆</div>
    <div class="div2">
        <div class="div2Child" style="margin-top: 50px">我是子div</div>
        <p style="color: white">我是父div</p>
    </div>
</body>

</html>


子div設置了margin-top以後,父div也跟着一塊兒margin-top了。ide

緣由以下:學習

Margin Collapsing 外邊距合併

塊的頂部外邊距和底部外邊距有時被組合(摺疊)爲單個外邊距,其大小是組合到其中的最大外邊距,這種行爲稱爲外邊距塌陷(margin collapsing),或外邊距合併。測試

外邊距合併的3中基本緣由:
一、相鄰的元素
毗鄰的兩個兄弟元素之間的外邊距會合並flex

二、塊級父元素與其第一個/最後一個子元素ui

  • 若是塊級父元素中,不存在border, padding, inline part, block formatting context created, or clearance 來隔離第一個子元素的上邊距,就會發送外邊距合併現象。
  • 若是塊級父元素,不存在border, padding, inline content, height, min-height, max-height來隔離下邊距,則會和最後一個子元素合併。

三、空塊元素
若是存在一個空的塊級元素,不存在 border、padding、inline content、height、min-height來隔離上下外邊距,那麼它的上下外邊距將會合並。spa

  • 當都爲正數時,取二者中較大者。
  • 當都爲負數時,取絕對值較大者。
  • 當一正一負時,取相加之和。
  • 外邊距設爲0時,這些規則也仍舊生效。

BFC(Block Formatting Context 塊格式化上下文)與元素外邊距合併 :code

  • 當兩個元素屬於不一樣的BFC時,這兩個元素的外邊距不會合並
  • 但在同一個BFC內,兩個相鄰元素的外邊距仍會合並。

Block Formatting Context 塊格式化上下文

一個塊格式化上下文(block formatting context) 是Web頁面的可視化CSS渲染出的一部分。它是塊級盒模型出現的區域,也是浮動元素與其餘元素進行交互的區域。orm

一個塊格式化上下文由如下之一建立:

  • 根元素或一些包含它的元素
  • 浮動元素 (元素的 float 不是 none)
  • 絕對定位元素 (元素的 position 爲 absolute 或 fixed)
  • 內聯塊 (元素具備 display: inline-block)
  • 表格單元格 (元素具備 display: table-cell,HTML表格單元格默認屬性)
  • 表格標題 (元素具備 display: table-caption, HTML表格標題默認屬性)
  • display隱式建立的匿名錶格列,包括table, table-row, table-row-group, table-header-group, table-footer-group (這些都是html的默認樣式), or inline-table
  • 具備overflow 且值不是 visible 的塊元素,
  • display: flow-root
  • flex 項目
  • grid 項目
  • 多列容器(column-count 和 column-width 不是 auto, 包括 column-count: 1的元素)
  • column-span: all 應當老是會建立一個新的格式化上下文,即使具備 column-span: all 的元素並不被包裹在一個多列容器中。

解決方案

知道了問題緣由所在,以及瞭解了相關原理,就很好辦了。
一、給div2設置border
爲了避免改變div2的大小,還需將設置 box-sizing爲border-box將padding和border包含在定義的width和height以內

.div2 {
    background: blue;
    height: 200px;
    border-top: 1px solid transparent;
    box-sizing: border-box;
}

二、去掉div2Child的margin,改成設置div2的padding

.div2 {
    background: blue;
    height: 200px;
    padding-top:50px;
    box-sizing: border-box;
}

三、div2設置爲內聯元素

.div2 {
    background: blue;
    height: 200px;
    display: inline-block;
    width: 100%;
}

四、清除浮動
全部浮動元素包含在div2內,增長樣式clearfix

.clearfix::before, .clearfix::after{
    overflow: hidden;
    display: table;
    visibility: hidden;
    content: '';
    clear: both;
}

或者建立一個新的BFC,使其在不一樣的上下文中,不合並外邊距。
五、給div2設置Position

.div2 {
    background: blue;
    height: 200px;
    position: absolute;
    width: 100%;
    max-width: 750px;
}

六、給div2設置float,注意後面的元素須要clear浮動

.div2 {
    background: blue;
    height: 200px;
    float: left;
    width: 100%;
}

七、給div2設置display

.div2 {
    background: blue;
    height: 200px;
    display: inline-block;
    /*display: table;*/
    width: 100%;
}

八、給div2設置flex

.div2 {
    background: blue;
    height: 200px;
    display: flex;
    flex-direction: column;
}

九、給div2設置overflow

.div2 {
    background: blue;
    height: 200px;
    overflow: hidden;
}

萬變不離其宗

參考

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context

相關文章
相關標籤/搜索