【轉】淺析BFC及其做用

1. 什麼是BFC 

BFC(block formatting context)簡單來講,BFC 就是一種屬性,這種屬性會影響着元素的定位以及與其兄弟元素之間的相互做用。 
中文譯爲塊級格式化上下文。是 W3C CSS 2.1 規範中的一個概念,它決定了元素如何對其內容進行定位,以及與其餘元素的關係和相互做用。 在進行盒子元素佈局的時候,BFC提供了一個環境,在這個環境中按照必定規則進行佈局不會影響到其它環境中的佈局。好比浮動元素會造成BFC,浮動元素內部子元素的主要受該浮動元素影響,兩個浮動元素之間是互不影響的。 也就是說,若是一個元素符合了成爲BFC的條件,該元素內部元素的佈局和定位就和外部元素互不影響(除非內部的盒子創建了新的 BFC),是一個隔離了的獨立容器。(在 CSS3 中,BFC 叫作 Flow Root)。css

2.  造成 BFC 的條件 

  1. 根元素或其餘包含它的元素
  2. 浮動(元素的float不爲none)
  3. 絕對定位元素(position爲absolute或者fixed)
  4. 行內塊(display:inline-block)
  5. 表格單元格(display:table-cell,html表格單元格默認屬性)
  6. 表格標題(display:table-caption,html表格標題默認屬性)
  7. overflow的值不爲visible的元素(hidden,auto,scroll)
  8. 彈性盒flex boxes(display:flex或者inline-flex)

其中,最多見的就是overflow:hidden、float:left/right、position:absolute。也就是說,每次看到這些屬性的時候,就表明了該元素已經建立了一個BFC了。html

3. BFC的 特性

  1. 內部的盒會在垂直方向一個接一個排列(能夠看做BFC中有一個的常規流);
  2. 處於同一個BFC中的元素相互影響,可能會發生外邊距疊加,若是這兩個相鄰的塊框不屬於同一個塊級格式化上下文,那麼它們的外邊距就不會疊加。;
  3. 每一個元素的margin box的左邊,與容器塊border box的左邊相接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此;
  4. BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素,反之亦然;
  5. 計算BFC的高度時,考慮BFC所包含的全部元素,連浮動元素也參與計算;

    6. 浮動盒區域不疊加到BFC上;chrome

BFC包含建立該上下文元素的全部子元素,但不包括建立了新BFC的子元素的內部元素,也就是一個元素不能同時存在於兩個BFC中。瀏覽器

通俗地來講:建立了 BFC的元素就是一個獨立的盒子,裏面的子元素不會在佈局上影響外面的元素,反之亦然,同時BFC仍然屬於文檔中的普通流。佈局

4. BFC常見做用

(1)包含浮動元素 
問題案例:高度塌陷問題:在一般狀況下父元素的高度會被子元素撐開,而在這裏由於其子元素爲浮動元素因此父元素髮生了高度坍塌,上下邊界重合。這時就能夠用bfc來清除浮動了。 
這裏寫圖片描述flex

(2)不被浮動元素覆蓋 
問題案例: div浮動兄弟遮蓋問題:因爲左側塊級元素髮生了浮動,因此和右側未發生浮動的塊級元素不在同一層內,因此會發生div遮擋問題。能夠給藍色塊加 overflow: hidden,觸發bfc來解決遮擋問題。 
這裏寫圖片描述spa

(3)BFC 會阻止外邊距摺疊 
問題案例:margin塌陷問題:在標準文檔流中,塊級標籤之間豎直方向的margin會以大的爲準,這就是margin的塌陷現象。能夠用overflow:hidden產生bfc來解決。 
這裏寫圖片描述.net

5. 從實際代碼來分析BFC 

實例一

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>高度坍塌問題-BFC模式解析</title>
    <style>
    * {
        margin: 0;
        padding: 0;
    }
    .box{
        background:#888;  /* 灰色 */
        height: 100%;
        margin-left: 50px;
    }
    .left{
        background: #73DE80;    /* 綠色 */
        opacity: 0.5;
        border: 3px solid #F31264;
        width: 200px;
        height: 200px;
        float: left;
    }
    .right{                     /* 粉色 */
        background: #EF5BE2;
        opacity: 0.5;
        border: 3px solid #F31264;
        width:400px;
        min-height: 100px;
    }

    </style>
</head>
<body>
    <div class='box'>
        <div class='left'></div>
        <div class='right'></div>
    </div>
</body>
</html> 

  綠色框('#left')向左浮動,它建立了一個新BFC,但暫時不討論它所建立的BFC。因爲綠色框浮動了,它脫離了本來normal flow的位置,所以,粉色框('#right')就被定位到灰色父元素的左上角(特性3:元素左邊與容器左邊相接觸),與浮動綠色框發生了重疊。firefox

  同時,因爲灰色框('#box')並無建立BFC,所以在計算高度的時候,並無考慮綠色框的區域,發生了高度坍塌,這也是常見問題之一。調試

實例二

如今經過設置overflow:hidden來建立BFC閉合浮動,再看看效果如何。

.BFC{
    overflow: hidden;
}

<div class='box BFC'>
    <div class='left'> </div>
    <div class='right'> </div>
</div>

灰色框建立了一個新的BFC後,高度發生了變化,計算高度時它將綠色框區域也考慮進去了(特性5:計算BFC的高度時,浮動元素也參與計算);而綠色框和紅色框的顯示效果仍然沒有任何變化。

 實例三 

如今,現將一些小塊添加到粉色框中,看看效果:

<style>
    .little{
        background: #fff;
        width: 50px;
        height: 50px;
        margin: 10px;
        float: left;
    }
</style>

<div class='box BFC'>
    <div class='left'> </div>
    <div class='right'>
        <div class='little'></div>
        <div class='little'></div>
        <div class='little'></div>
    </div>
</div>

 因爲粉紅框沒有建立新的BFC,所以粉色框中白色塊受到了綠色框的影響,被擠到了右邊去了(特性6:浮動盒區域不疊加到BFC上)。先無論這個,看看白色塊的margin,發生了外邊距疊加。

實例四

利用同實例二中同樣的方法,爲粉色框建立BFC,防止與浮動元素(綠色框)重疊:

<div class='box BFC'>
    <div class='left'> </div>
    <div class='right BFC'>
        <div class='little'></div>
        <div class='little'></div>
        <div class='little'></div>
    </div>
</div>

一旦粉色框建立了新的BFC之後,粉色框就不與綠色浮動框發生重疊了,同時內部的白色塊處於隔離的空間(特性4:BFC就是頁面上的一個隔離的獨立容器),白色塊也不會受到綠色浮動框的擠壓。

總結

 以上就是BFC的分析,BFC的概念比較抽象,但經過實例分析應該可以更好地理解BFC。在實際中,利用BFC能夠閉合浮動(實例二),防止與浮動元素重疊(實例四)。同時,因爲BFC的隔離做用,能夠利用BFC包含一個元素,防止這個元素與BFC外的元素髮生margin collapse。

 5. 那麼到底爲何坍塌?

  float 脫離了普通流,而且建立了新的BFC,而父元素不具有產生 BFC 的條件,因此它的高度爲0。

如何解決?

  經過了解BFC的特性咱們知道,BFC會把它包含的浮動元素高度也算在裏面,也就是閉合浮動。拿 overflow: auto 舉例:overflow: auto 並不會閉合浮動,而是 overflow: auto 會建立一個新的BFC,避免浮動的元素侵入其餘元素。

  IE6-7有一個特有的屬性就是haslayout,當一個元素的hasLayout屬性值爲true時,咱們說這個元素有一個佈局(layout)它負責對本身和可能的後代元素進行尺寸計算和定位,當屬性值爲false時,它的尺寸和位置由最近擁有佈局的祖先元素控制。

  不少狀況下,把 hasLayout的狀態改爲true 能夠解決很大部分ie下顯示的bug。 hasLayout屬性不能直接設定,經過設定一些特定的css屬性來觸發並改變 hasLayout 狀態。

  元素hasLayout而致使的問題其實通常都很容易發現:每每是內容出現錯位甚至徹底不可見。 如:當一個元素內含浮動或絕對定位的內容時,它一般會表現出奇怪和錯誤的行爲

  通常若是是由於layout而引發的顯示不符指望效果的話,在ff下會表現正常,而在ie下會出現錯誤。這個時候能夠嘗試觸發父容器及其中的子容器的haslayout屬性,一般能夠經過加上zoom: 1;來調試。直到找到了產生問題的元素,再進行鍼對性的修正。最好的辦法是對這個元素設置尺寸屬性。可是,有時不便指定尺寸屬性的狀況下,就只能尋找替代方案了。對於ie7 ,最好的辦法是設置最小高度屬性爲0;這個技術是無害的,由於0原本就是這個屬性的初始值。並且沒有必要對其餘瀏覽器隱藏這個屬性。而對於ie6和更早版本中觸發一個元素hasLayout的方法是在overflow屬性是visible的狀況下設置這個元素的高度屬性爲1%,而後對其餘瀏覽器隱藏這個設置。這種技術就是著名的Holly hack。

觸發hasLayout的條件:

position: absolute
float: left|right
display: inline-block
width: 除 「auto」 外的任意值
height: 除 「auto」 外的任意值 (例如不少人閉合浮動會用到 height: 1% )
zoom: 除 「normal」 外的任意值
writing-mode: tb-rl 
在 IE7 中,一些額外的屬性也能夠觸發該屬性:

min-height: (任何值)

max-height: (任何值除了none)
min-width: (任何值)
max-width: (任何值除了none)
overflow: hidden|scroll|auto ( 這個屬性在IE以前版本中沒有觸發 layout 的功能。 )
overflow-x|-y: hidden|scroll|auto (CSS3 盒模型中的屬性,還沒有獲得瀏覽器的普遍支持。他們在以前IE版本中一樣沒有觸發 layout 的功能)

綜上所述:

在支持BFC的瀏覽器(IE8+,firefox,chrome,safari)經過建立新的BFC閉合浮動;

在不支持 BFC的瀏覽器 (IE6-7),經過觸發 hasLayout 閉合浮動。

 

參考: 高度坍塌問題--BFC模式解析

    淺析BFC及其做用

相關文章
相關標籤/搜索