margin疊加和BFC

引子

自己最初根本不知道 BFC 和 margin 疊加的概念,但是在寫 web 簡歷頁面的時(shí)候發(fā)現(xiàn)個(gè)奇怪的現(xiàn)象,才了解到原來 CSS 還有這么個(gè)神奇的東西。先簡單說說當(dāng)初遇到的現(xiàn)象吧,就是下面這樣:

html:

<body>
    <div class="first-block"></div>
    <div class="second-block">
        <h2>title</h2>
    </div>
</body>

css:

.first-block
{
    background: #F44336;
    width: 200px;
    height: 200px;
}
.second-block
{
    background: #00BCD4;
    width: 200px;
    height: 200px;
}

很簡單是吧,可是看到瀏覽器中的效果時(shí)我還是有點(diǎn)懵逼,是這樣的:

為什么 first-block 和 second-block 之間會(huì)有這么寬的間距?我并沒有給他們設(shè)置 margin 啊!

原因

外邊距折疊

那么為什么會(huì)這樣呢,先自己動(dòng)手找下原因吧,F(xiàn)12審查下元素,很快找到原因了:

原來這個(gè)間距是h2的上外邊距引起的,可是 h2 不是 second-block 的子元素么,為什么它的 margin 可以穿透出去頂?shù)?first-block ?

不懂就google一下吧,沒費(fèi)多大勁就找到原因了:

在CSS當(dāng)中,相鄰的兩個(gè)盒子(可能是兄弟關(guān)系也可能是祖先關(guān)系)的外邊距可以結(jié)合成一個(gè)單獨(dú)的外邊距。這種合并外邊距的方式被稱為折疊,并且因而所結(jié)合成的外邊距稱為折疊外邊距。

原來是外邊距折疊造成的,以前也在head first上看到過這個(gè)概念,但是當(dāng)時(shí)書上只提到說兩個(gè)相鄰的塊元素的上下外邊框直接會(huì)產(chǎn)生折疊現(xiàn)象,當(dāng)時(shí)想當(dāng)然地以為所謂的相鄰的塊元素是指兩個(gè)兄弟關(guān)系的塊元素,沒想到也包括祖先關(guān)系。

折疊的條件

兩個(gè)塊元素要產(chǎn)生折疊現(xiàn)象,必須滿足一個(gè)必備條件,那就是這兩個(gè)元素的 margin 必須是相鄰的,那么如果定義相鄰呢,w3c 規(guī)范,兩個(gè) margin 是鄰接的必須滿足以下條件:

  • 必須是處于常規(guī)文檔流(非float和絕對定位)的塊級(jí)盒子,并且處于同一個(gè) BFC 當(dāng)中。
  • 沒有inline盒子,沒有空隙,沒有 padding 和 border 將他們分隔開。
  • 都屬于垂直方向上相鄰的外邊距,可以是下面任意一種情況:
    • 元素的 margin-top 與其第一個(gè)常規(guī)文檔流的子元素的 margin-top。
    • 元素的 margin-bottom 與其下一個(gè)常規(guī)文檔流的兄弟元素的 margin-top。
    • height 為 auto 的元素的 margin-bottom 與其最后一個(gè)常規(guī)文檔流的子元素的 margin-bottom。
    • 高度為0并且最小高度也為0,不包含常規(guī)文檔流的子元素,并且自身沒有建立新的BFC的元素的 margin-top 和 margin-bottom。

BFC

好不容易才理解了折疊,怎么又跑出來個(gè)BFC?繼續(xù)google吧:

BFC(Block formatting context)直譯為"塊級(jí)格式化上下文"。它是一個(gè)獨(dú)立的渲染區(qū)域,只有 Block-level box 參與, 它規(guī)定了內(nèi)部的 Block-level Box 如何布局,并且與這個(gè)區(qū)域外部毫不相干。

簡單來說,CSS 里的布局和渲染都是以 Box 為單位的,不同的 Box 有不同的布局規(guī)則,而 BFC 是其中的一種,相似的還有 IFC 和 CSS3 中增加的 GFC 和 FFC,這里就不深入介紹了。

BFC布局規(guī)則

BFC 的布局遵從如下規(guī)則:

  • 內(nèi)部的 Box 會(huì)在垂直方向,一個(gè)接一個(gè)地放置。
  • Box 垂直方向的距離由 margin 決定。屬于同一個(gè) BFC 的兩個(gè)相鄰 Box 的 margin 會(huì)發(fā)生重疊
  • 每個(gè)元素的 margin box 的左邊, 與包含塊 border box 的左邊相接觸(對于從左往右的格式化,否則相反)。即使存在浮動(dòng)也是如此。
  • BFC 的區(qū)域不會(huì)與 float box 重疊。
  • BFC 就是頁面上的一個(gè)隔離的獨(dú)立容器,容器里面的子元素不會(huì)影響到外面的元素。反之也如此。
  • 計(jì)算BFC的高度時(shí),浮動(dòng)元素也參與計(jì)算。

哪些元素會(huì)生成BFC

  • 根元素。
  • float 屬性不為 none。
  • position 為 absolute 或 fixed。
  • display 為 inline-block, table-cell, table-caption, flex, inline-flex。
  • overflow 不為 visible(hidden, scroll, auto)。

結(jié)合 BFC 布局規(guī)則一看,以前學(xué)過的好多 CSS 規(guī)則方法的原理都在 BFC 這啊,比如最常用的清除浮動(dòng)什么的。

解決方案

知道了問題產(chǎn)生的原因,那就可以對癥下藥了。

  • 方法一

    我們注意到折疊條件的第二條:沒有inline盒子,沒有空隙,沒有 padding 和 border 將他們分隔開。 自然而然地就可以想到我們可以把 second-block 加上一個(gè)邊框來讓折疊失效:

    修改css:

    .second-block
    {
        background: #00BCD4;
        width: 200px;
        height: 200px;
        border: 1px solid rgba(0,0,0,0); /*添加一個(gè)透明邊框*/
    }
    

    效果:

    嗯,折疊問題解決了,但是由于有1px的邊框,second-block 看起來會(huì)比 first-block 寬一點(diǎn),沒關(guān)系,添加box-sizing: border-box屬性可以解決這個(gè)問題:

    修改css:

    .second-block
    {
        background: #00BCD4;
        width: 200px;
        height: 200px;
        border: 1px solid rgba(0,0,0,0); /*添加一個(gè)透明邊框*/
        box-sizing: border-box;
    }
    

    效果:

  • 方法二

    我們知道,這里之所以會(huì)產(chǎn)生折疊,是因?yàn)閮蓚€(gè) block 處于同一個(gè) BFC(根元素生成的BFC)中,那我們可以讓 second-block 單獨(dú)生成一個(gè) BFC,就可以防止出現(xiàn)折疊了。

    修改css:

    .second-block
    {
        background: #00BCD4;
        width: 200px;
        height: 200px;
        overflow: hidden; /*觸發(fā)BFC*/
    }
    

    效果:

    嗯,完美~!

參考文章:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,796評論 1 92
  • 一,浮動(dòng)元素有什么特征?對父容器、其他浮動(dòng)元素、普通元素、文字分別有什么影響? 浮動(dòng)模型是一種可視化格式模型,浮動(dòng)...
    DeeJay_Y閱讀 901評論 0 4
  • relative:生成相對定位的元素,通過top,bottom,left,right的位置相對于其正常位置進(jìn)行定位...
    zx9426閱讀 965評論 0 2
  • 1.背景介紹 BFC全稱是Block Formatting Context,是CSS2.1規(guī)范定義的,關(guān)于CSS渲...
    你隔壁的陌生人閱讀 1,166評論 0 0
  • 已經(jīng)忘了有多久沒有好好寫點(diǎn)東西了。 上一次動(dòng)筆大概還是在五年前。剛剛步入成人世界的少年帶著稚氣和批判...
    多多是個(gè)五迷閱讀 285評論 6 2