BFC(Block Formatting Context)直譯爲「塊級格式化範圍」。 W3C CSS 2.1 規範中的一個概念,它決定了元素如何對其內容進行定位,以及與其餘元素的關係和相互做用。當涉及到可視化佈局的時候,Block Formatting Context提供了一個環境,HTML元素在這個環境中按照必定規則進行佈局。一個環境中的元素不會影響到其它環境中的佈局。好比浮動元素會造成BFC,浮動元素內部子元素的主要受該浮動元素影響,兩個浮動元素之間是互不影響的。這裏有點相似一個BFC就是一個獨立的行政單位的意思。也能夠說BFC就是一個做用範圍。能夠把它理解成是一個獨立的容器,而且這個容器的裏box的佈局,與這個容器外的絕不相干。html
另外一個通俗點的解釋是:在普通流中的 Box(框) 屬於一種 formatting context(格式化上下文) ,類型能夠是 block ,或者是inline ,但不能同時屬於這二者。而且, Block boxes(塊框) 在 block formatting context(塊格式化上下文) 裏格式化,Inline boxes(塊內框) 則在 inline formatting context(行內格式化上下文) 裏格式化。任何被渲染的元素都屬於一個box ,而且不是 block ,就是 inline 。即便是未被任何元素包裹的文本,根據不一樣的狀況,也會屬於匿名的 block boxes 或者 inline boxes。因此上面的描述,便是把全部的元素劃分到對應的 formatting context 裏。瀏覽器
有如下表現規則:ide
一、在建立了 Block Formatting Context 的元素中,其子元素按文檔流一個接一個地放置。垂直方向上他們的起點是一個包含塊的頂部,兩個相鄰的元素之間的垂直距離取決於 ‘margin’ 特性。佈局
根據 CSS 2.1 8.3.1 Collapsing margins 第一條,兩個相鄰的普通流中的塊框在垂直位置的空白邊會發生摺疊現象。也就是處於同一個BFC中的兩個垂直窗口的margin會重疊。ui
根據 CSS 2.1 8.3.1 Collapsing margins 第三條,生成 block formatting context 的元素不會和在流中的子元素髮生空白邊摺疊。因此解決這種問題的辦法是要爲兩個容器添加具備BFC的包裹容器。spa
二、在 Block Formatting Context 中,每個元素左外邊與包含塊的左邊相接觸(對於從右到左的格式化,右外邊接觸右邊),即便存在浮動也是如此(儘管一個元素的內容區域會因爲浮動而壓縮),除非這個元素也建立了一個新的 Block Formatting Context 。firefox
三、Block Formatting Context就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會在佈局上影響到外面的元素,反之也是如此。orm
四、根據 CSS 2.1 9.5 Floats 中的描述,建立了 Block Formatting Context 的元素不能與浮動元素重疊。htm
表格的 border-box、塊級的替換元素、或是在普通流中建立了新的 block formatting context(如元素的 'overflow' 特性不爲 'visible' 時)的元素不能夠與位於相同的 block formatting context 中的浮動元素相重疊。blog
5 、當容器有足夠的剩餘空間容納 BFC 的寬度時,全部瀏覽器都會將 BFC 放置在浮動元素所在行的剩餘空間內。
六、 在 IE6 IE7 IE8 Chrome Opera 中,當 BFC 的寬度介於 "容器剩餘寬度" 與 "容器寬度" 之間時,BFC 會顯示在浮動元素的下一行;在 Safari 中,BFC 則仍然保持顯示在浮動元素所在行,而且 BFC 溢出容器;在 Firefox 中,當容器自己也建立了 BFC 或者容器的 'padding-top'、'border-top-width' 這些特性不都爲 0 時表現與 IE8(S)、Chrome 相似,不然表現與 Safari 相似。
經驗證,最新版本的瀏覽中只有firefox會在同一行顯示,其它瀏覽器均換行。
七、 在 IE6 IE7 IE8 Opera 中,當 BFC 的寬度大於 "容器寬度" 時,BFC 會顯示在浮動元素的下一行;在 Chrome Safari 中,BFC 則仍然保持顯示在浮動元素所在行,而且 BFC 溢出容器;在 Firefox 中,當容器自己也建立了 BFC 或者容器的 'padding- top'、'border-top-width' 這些特性不都爲 0 時表現與 IE8(S) 相似,不然表現與 Chrome 相似。
經驗證,最新版本的瀏覽中只有firefox會在同一行顯示,其它瀏覽器均換行。
八、根據CSS2.1 規範第10.6.7部分的高度計算規則,在計算生成了 block formatting context 的元素的高度時,其浮動子元素應該參與計算。
下面先看一個比較典型的例子:
<</span>html>
<</span>head>
<</span>meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<</span>title>無標題文檔</</span>title>
<</span>style>
* { padding:0; margin:0; }
#red, #yellow, #orange, #green { width:100px; height:100px; float:left; }
#red { background-color:red; } #yellow { background-color:yellow; }
#orange { background-color:orange; }
#green { background-color:green; }
</</span>style>
</</span>head>
<</span>body>
<</span>div id="c1">
<</span>div id="red">
</</span>div>
<</span>div id="yellow">
</</span>div>
</</span>div>
<</span>div id="c2">
<</span>div id="orange">
</</span>div>
<</span>div id="green">
</</span>div>
</</span>div>
<</span>p>Here is the text!</</span>p>
</</span>body>
</</span>
該段代碼本意要造成兩行兩列的佈局,可是因爲#red,#yellow,#orange,#green四個div在同一個佈局環境BFC中,所以雖然它們位於兩個不一樣的div(#c1和#c2)中,但仍然不會換行,而是一行四列的排列。
若要使之造成兩行兩列的佈局,就要建立兩個不一樣的佈局環境,也能夠說要建立兩個BFC。那到底怎麼建立BFC呢?
上面的例子,再加兩行代碼,建立兩個BFC:
#c1{overflow:hidden;} #c2{overflow:hidden;}
![](http://static.javashuo.com/static/loading.gif)
上面建立了兩個佈局環境BFC。內部子元素的左浮動不會影響到外部元素。因此#c1和#c2沒有受浮動的影響,仍然各自佔據一行!
a、不和浮動元素重疊
若是一個浮動元素後面跟着一個非浮動的元素,那麼就會產生一個覆蓋的現象,不少自適應的兩欄佈局就是這麼作的。
看下面一個例子
<</span>html>
<</span>head>
<</span>meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<</span>title>無標題文檔</</span>title>
<</span>style>
html,body {height:100%; }
* { padding:0; margin:0; color:#fff; text-decoration:none; list-style:none; font-family:"微軟雅黑" }
.aside{background:#f00;width:170px;float:left;height:300px;}
.main{background:#090;height:100%;}
</</span>style>
</</span>head>
<</span>body>
<</span>div class="aside"> </</span>div>
<</span>div class="main"> </</span>div>
</</span>body>
</</span>html>
很明顯,.aside和.mian重疊了。試分析一下,因爲兩個box都處在同一個BFC中,都是以BFC邊界爲起點,若是兩個box自己都具有BFC的話,會按順序一個一個排列布局,如今.main並不具有BFC,按照規則2,內部元素都會從左邊界開始,除非它自己具有BFC,按上面規則4擁有BFC的元素是不能夠跟浮動元素重疊的,因此只要爲.mian再建立一個BFC,就能夠解決這個重疊的問題。上面已經說過建立BFC的方法,能夠根據具體狀況選用不一樣的方法,這裏我選用的是加overflow:hidden。
因爲ie的緣由須要再加一個解發haslayout的zoom:1,有關haslayout後面會講到。
b、清除元素內部浮動
只要把父元素設爲BFC就能夠清理子元素的浮動了,最多見的用法就是在父元素上設置overflow: hidden樣式,對於IE6加上zoom:1就能夠了(IE Haslayout)。
看下面例子:
<</span>html>
<</span>head>
<</span>meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<</span>title>無標題文檔</</span>title>
<</span>style> html,body {height:100%; }
* { padding:10px; margin:0; color:#000; text-decoration:none; list-style:none; font-family:"微軟雅黑" }
.outer{width:300px;border:1px solid #666;padding:10px;}
.innerLeft{height:100px;width:100px;float:left;background:#f00;}
.innerRight{height:100px;width:100px;float:right;background:#090;}
</</span>style>
</</span>head>
<</span>body>
<</span>div class="outer">
<</span>div class="innerLeft"></</span>div>
<</span>div class="innerRight"></</span>div>
</</span>div>
</</span>body>
</</span>html>
根據 CSS2.1 規範第 10.6.3 部分的高度計算規則,在進行普通流中的塊級非替換元素的高度計算時,浮動子元素不參與計算。
同時 CSS2.1 規範第10.6.7部分的高度計算規則,在計算生成了 block formatting context 的元素的高度時,其浮動子元素應該參與計算。
因此,觸發外部容器BFC,高度將從新計算。好比給outer加上屬性overflow:hidden觸發其BFC。
c、解決上下相鄰兩個元素重疊
看下面例子:
<</span>html>
<</span>head>
<</span>meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<</span>title>無標題文檔</</span>title>
<</span>style>
html,body {height:100%; }
* { padding:0; margin:0; color:#fff; text-decoration:none; list-style:none; font-family:"微軟雅黑" }
.rowone{background:#f00;height:100px;margin-bottom:20px;overflow:hidden;}
.rowtow{background:#090;height:100px;margin-top:20px;position:relative}
</</span>style>
</</span>head>
<</span>body>
<</span>div class="rowone"> </</span>div>
<</span>div class="rowtow"> </</span>div>
</</span>body>
</</span>html>
根據 CSS 2.1 8.3.1 Collapsing margins 第一條,兩個相鄰的普通流中的塊框在垂直位置的空白邊會發生摺疊現象。也就是處於同一個BFC中的兩個垂直窗口的margin會重疊。
根據 CSS 2.1 8.3.1 Collapsing margins 第三條,生成 block formatting context 的元素不會和在流中的子元素髮生空白邊摺疊。因此解決這種問題的辦法是要爲兩個容器添加具備BFC的包裹容器。
因此解這個問題的辦法就是,把兩個容器分別放在兩個據有BFC的包裹容器中,IE裏就是觸發layout的兩個包裹容器中!
<</span>html>
<</span>head>
<</span>meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<</span>title>無標題文檔</</span>title>
<</span>style>
html, body { height:100%; }
* { padding:0; margin:0; color:#fff; text-decoration:none; list-style:none; font-family:"微軟雅黑" }
.mg {overflow:hidden; }
.rowone { background:#f00; height:100px; margin-bottom:20px; }
.rowtow { background:#090; height:100px; margin-top:20px; }
</</span>style>
</</span>head>
<</span>body>
<</span>div class="mg">
<</span>div class="rowone"> </</span>div>
</</span>div>
<</span>div class="mg">
<</span>div class="rowtow"> </</span>div>
</</span>div>
</</span>body>
</</span>html>