BFC是什麼?有什麼做用?

---恢復內容開始---html

BFCBlock 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

3Block Formatting Context就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會在佈局上影響到外面的元素,反之也是如此。設計

4、根據 CSS 2.1 9.5 Floats 中的描述,建立了 Block Formatting Context 的元素不能與浮動元素重疊。

    表格的 border-box、塊級的替換元素、或是在普通流中建立了新的 block formatting context(如元素的 'overflow' 特性不爲 'visible' 時)的元素不能夠與位於相同的 block formatting context 中的浮動元素相重疊。

、當容器有足夠的剩餘空間容納 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的值不爲relativestatic

若是還其它方式,請在回覆中給出,我會及時更新!!

上面的例子,我再加兩行代碼,建立兩個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的緣由須要再加一個解發haslayoutzoom: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、什麼是IEhaslayout

上面的例子中咱們用到了IEzoom:1;其實是觸發了IElayoutLayout 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>

 

須要觸發.mglayout才能解決margin重疊問題

運行效果以下:

 

上面有關BFC所舉的例子,在IE6\7中觸發layout均可以解決,能夠本身動手試一下,這裏就不重複舉例了。

  

 

 

 

  

 

 

---恢復內容結束---

相關文章
相關標籤/搜索