---恢復內容開始---html
BFC(Block Formatting Context)直譯爲「塊級格式化範圍」。前端
是 W3C CSS 2.1 規範中的一個概念,它決定了元素如何對其內容進行定位,以及與其餘元素的關係和相互做用。當涉及到可視化佈局的時候,Block Formatting Context提供了一個環境,HTML元素在這個環境中按照必定規則進行佈局。一個環境中的元素不會影響到其它環境中的佈局。好比浮動元素會造成BFC,浮動元素內部子元素的主要受該浮動元素影響,兩個浮動元素之間是互不影響的。這裏有點相似一個BFC就是一個獨立的行政單位的意思。也能夠說BFC就是一個做用範圍。能夠把它理解成是一個獨立的容器,而且這個容器的裏box的佈局,與這個容器外的絕不相干。瀏覽器
另外一個通俗點的解釋是:在普通流中的 Box(框) 屬於一種 formatting context(格式化上下文) ,類型能夠是 block ,或者是 inline ,但不能同時屬於這二者。而且, Block boxes(塊框) 在 block formatting context(塊格式化上下文) 裏格式化, Inline boxes(塊內框) 則在 inline formatting context(行內格式化上下文) 裏格式化。任何被渲染的元素都屬於一個 box ,而且不是 block ,就是 inline 。即便是未被任何元素包裹的文本,根據不一樣的狀況,也會屬於匿名的 block boxes 或者 inline boxes。因此上面的描述,便是把全部的元素劃分到對應的 formatting context 裏。app
其通常表現規則,我整理了如下這幾個狀況:ide
1、在建立了 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
2、在 Block Formatting Context 中,每個元素左外邊與包含塊的左邊相接觸(對於從右到左的格式化,右外邊接觸右邊), 即便存在浮動也是如此(儘管一個元素的內容區域會因爲浮動而壓縮),除非這個元素也建立了一個新的 Block Formatting Context 。firefox
3、Block Formatting Context就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會在佈局上影響到外面的元素,反之也是如此。設計
4、根據 CSS 2.1 9.5 Floats 中的描述,建立了 Block Formatting Context 的元素不能與浮動元素重疊。
表格的 border-box、塊級的替換元素、或是在普通流中建立了新的 block formatting context(如元素的 'overflow' 特性不爲 'visible' 時)的元素不能夠與位於相同的 block formatting context 中的浮動元素相重疊。
5 、當容器有足夠的剩餘空間容納 BFC 的寬度時,全部瀏覽器都會將 BFC 放置在浮動元素所在行的剩餘空間內。
6、 在 IE6 IE7 IE8 Chrome Opera 中,當 BFC 的寬度介於 "容器剩餘寬度" 與 "容器寬度" 之間時,BFC 會顯示在浮動元素的下一行;在 Safari 中,BFC 則仍然保持顯示在浮動元素所在行,而且 BFC 溢出容器;在 Firefox 中,當容器自己也建立了 BFC 或者容器的 'padding-top'、'border-top-width' 這些特性不都爲 0 時表現與 IE8(S)、Chrome 相似,不然表現與 Safari 相似。
經驗證,最新版本的瀏覽中只有firefox會在同一行顯示,其它瀏覽器均換行。
7、 在 IE6 IE7 IE8 Opera 中,當 BFC 的寬度大於 "容器寬度" 時,BFC 會顯示在浮動元素的下一行;在 Chrome Safari 中,BFC 則仍然保持顯示在浮動元素所在行,而且 BFC 溢出容器;在 Firefox 中,當容器自己也建立了 BFC 或者容器的 'padding- top'、'border-top-width' 這些特性不都爲 0 時表現與 IE8(S) 相似,不然表現與 Chrome 相似。
經驗證,最新版本的瀏覽中只有firefox會在同一行顯示,其它瀏覽器均換行。
8、根據CSS2.1 規範第10.6.7部分的高度計算規則,在計算生成了 block formatting context 的元素的高度時,其浮動子元素應該參與計算。
若是還有其它狀況,請各位回得中補充,我會及時更新!
下面先看一個比較典型的例子:
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>無標題文檔</title> <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; } </style> </head> <body> <div id="c1"> <div id="red"> </div> <div id="yellow"> </div> </div> <div id="c2"> <div id="orange"> </div> <div id="green"> </div> </div> <p>Here is the text!</p> </body> </html>
效果以下:
該段代碼本意要造成兩行兩列的佈局,可是因爲#red,#yellow,#orange,#green四個div在同一個佈局環境BFC中,所以雖然它們位於兩個不一樣的div(#c1和#c2)中,但仍然不會換行,而是一行四列的排列。
若要使之造成兩行兩列的佈局,就要建立兩個不一樣的佈局環境,也能夠說要建立兩個BFC。那到底怎麼建立BFC呢?
2、如何產生BFC:當一個HTML元素知足下面條件的任何一點,均可以產生Block Formatting Context:
float的值不爲none。
overflow的值不爲visible。
display的值爲table-cell, table-caption, inline-block中的任何一個。
position的值不爲relative和static。
若是還其它方式,請在回覆中給出,我會及時更新!!
上面的例子,我再加兩行代碼,建立兩個BFC:
#c1{overflow:hidden;} #c2{overflow:hidden;}
效果以下:
上面建立了兩個佈局環境BFC。內部子元素的左浮動不會影響到外部元素。因此#c1和#c2沒有受浮動的影響,仍然各自佔據一行!
3、BFC能用來作什麼?
a、不和浮動元素重疊
若是一個浮動元素後面跟着一個非浮動的元素,那麼就會產生一個覆蓋的現象,不少自適應的兩欄佈局就是這麼作的。
看下面一個例子
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>無標題文檔</title> <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%; } </style> </head> <body> <div class="aside"> </div> <div class="main"> </div> </body> </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)。
看下面例子:
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>無標題文檔</title> <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; } </style> </head> <body> <div class="outer"> <div class="innerLeft"></div> <div class="innerRight"></div> </div> </div> </body> </html>
根據 CSS2.1 規範第 10.6.3 部分的高度計算規則,在進行普通流中的塊級非替換元素的高度計算時,浮動子元素不參與計算。
同時 CSS2.1 規範第10.6.7部分的高度計算規則,在計算生成了 block formatting context 的元素的高度時,其浮動子元素應該參與計算。
因此,觸發外部容器BFC,高度將從新計算。好比給outer加上屬性overflow:hidden觸發其BFC。
c、解決上下相鄰兩個元素重疊
看下面例子:
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>無標題文檔</title> <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 } </style> </head> <body> <div class="rowone"> </div> <div class="rowtow"> </div> </body> </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的兩個包裹容器中!
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>無標題文檔</title> <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; } </style> </head> <body> <div class="mg"> <div class="rowone"> </div> </div> <div class="mg"> <div class="rowtow"> </div> </div> </body> </html>
效果以下:
4、什麼是IE的haslayout
上面的例子中咱們用到了IE的zoom:1;其實是觸發了IE的layout。Layout 是 IE 瀏覽器渲染引擎的一個內部組成部分。在 IE 瀏覽器中,一個元素要麼本身對自身的內容進行組織和計算大小, 要麼依賴於包含塊來計算尺寸和組織內容。爲了協調這兩種方式的矛盾,渲染引擎採用了 ‘hasLayout’ 屬性,屬性值能夠爲 true 或 false。 當一個元素的 ‘hasLayout’ 屬性值爲 true 時,咱們說這個元素有一個佈局(layout),或擁有佈局。能夠經過 hasLayout 屬性來判斷一個元素是否擁有 layout ,
如 object.currentStyle.hasLayout 。
hasLayout 與 BFC 有不少類似之處,但 hasLayout 的概念會更容易理解。在 Internet Explorer 中,元素使用「佈局」概念來控制尺寸和定位,分爲擁有佈局和沒有佈局兩種狀況,擁有佈局的元素由它控制自己及其子元素的尺寸和定位,而沒有佈局的元素則經過父元素(最近的擁有佈局的祖先元素)來控制尺寸和定位,而一個元素是否擁有佈局則由 hasLayout 屬性告知瀏覽器,它是個布爾型變量,true 表明元素擁有佈局,false 表明元素沒有佈局。簡而言之,hasLayout 只是一個 IE 下專有的屬性,hasLayout 爲 true 的元素瀏覽器會賦予它一系列的效果。
特別注意的是,hasLayout 在 IE 8 及以後的 IE 版本中已經被拋棄,因此在實際開發中只需針對 IE 8 如下的瀏覽器爲某些元素觸發 hasLayout。
5、怎樣觸發layout
一個元素觸發 hasLayout 會影響一個元素的尺寸和定位,這樣會消耗更多的系統資源,所以 IE 設計者默認只爲一部分的元素觸發 hasLayout (即默認有部分元素會觸發 hasLayout ,這與 BFC 基本徹底由開發者經過特定 CSS 觸發並不同),這部分元素以下:
<html>, <body> <table>, <tr>, <th>, <td> <img> <hr> <input>, <button>, <select>, <textarea>, <fieldset>, <legend> <iframe>, <embed>, <object>, <applet> <marquee>
除了 IE 默認會觸發 hasLayout 的元素外,Web 開發者還可使用特定的 CSS 觸發元素的 hasLayout 。
經過爲元素設置如下任一 CSS ,能夠觸發 hasLayout (即把元素的 hasLayout 屬性設置爲 true)。
display: inline-block height: (除 auto 外任何值) width: (除 auto 外任何值) float: (left 或 right) position: absolute writing-mode: tb-rl zoom: (除 normal 外任意值) min-height: (任意值) min-width: (任意值) max-height: (除 none 外任意值) max-width: (除 none 外任意值) overflow: (除 visible 外任意值,僅用於塊級元素) overflow-x: (除 visible 外任意值,僅用於塊級元素) overflow-y: (除 visible 外任意值,僅用於塊級元素) position: fixed
對於內聯元素(能夠是默認被瀏覽器認爲是內聯元素的 span 元素,也能夠是設置了 display: inline 的元素),width 和 height 只在 IE5.x 下和 IE6 或更新版本的 quirks 模式下能觸發元素的 hasLayout ,可是對於 IE6,若是瀏覽器運行於標準兼容模式下,內聯元素會忽略 width 或 height 屬性,因此設置 width 或 height 不能在此種狀況下令該元素觸發 hasLayout 。但 zoom 除了在 IE 5.0 中外,老是能觸發 hasLayout 。zoom 用於設置或檢索元素的縮放比例,爲元素設置 zoom: 1 既能夠觸發元素的 hasLayout 同時不會對元素形成多餘的影響。所以綜合考慮瀏覽器之間的兼容和對元素的影響, 建議使用 zoom: 1 來觸發元素的 hasLayout 。
6、能解決的問題
hasLayout表現出來的特性跟BFC很類似,因此能夠認爲是IE中的BFC。上面的規則幾乎都遵循,因此上面的問題在IE裏均可以經過觸發hasLayout來解決。
雖然 hasLayout 也會像 BFC 那樣影響着元素的尺寸和定位,但它卻又不是一套完整的標準,而且因爲它默認只爲某些元素觸發,這致使了 IE 下不少前端開發的 bugs ,觸發 hasLayout 更大的意義在於解決一些 IE 下的 bugs ,而不是利用它的一些「反作用」來達到某些效果。另外因爲觸發 hasLayout 的元素會出現一些跟觸發 BFC 的元素類似的效果,所以爲了統一元素在 IE 與支持 BFC 的瀏覽器下的表現,Kayo 建議爲觸發了 BFC 的元素同時觸發 hasLayout ,固然還須要考慮實際的狀況,也有可能只需觸發其中一個就能夠達到表現統一,下面會舉例介紹。
這裏首先列出觸發 hasLayout 元素的一些效果:
a、阻止外邊距摺疊
如上面例子:
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>無標題文檔</title> <style> html, body { height: 100%; } * { padding: 0; margin: 0; color: #fff; text-decoration: none; list-style: none; font-family: "微軟雅黑" } .mg { zoom: 1 } .rowone { background: #f00; height: 100px; margin-bottom: 20px; } .rowtow { background: #090; height: 100px; margin-top: 20px; } </style> </head> <body> <div class="mg"> <div class="rowone"> </div> </div> <div class="mg"> <div class="rowtow"> </div> </div> </body> </html>
須要觸發.mg的layout才能解決margin重疊問題
運行效果以下:
上面有關BFC所舉的例子,在IE6\7中觸發layout均可以解決,能夠本身動手試一下,這裏就不重複舉例了。
---恢復內容結束---