BFC是什么?有什么作用?


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

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 里。

其一般表現規則,我整理了以下這幾個情況:

1、在創建了 Block Formatting Context 的元素中,其子元素按文檔流一個接一個地放置。垂直方向上他們的起點是一個包含塊的頂部,兩個相鄰的元素之間的垂直距離取決於 ‘margin’ 特性。

    根據 CSS 2.1 8.3.1 Collapsing margins 第一條,兩個相鄰的普通流中的塊框在垂直位置的空白邊會發生折疊現象。也就是處於同一個BFC中的兩個垂直窗口的margin會重疊。

    根據 CSS 2.1 8.3.1 Collapsing margins 第三條,生成 block formatting context 的元素不會和在流中的子元素發生空白邊折疊。所以解決這種問題的辦法是要為兩個容器添加具有BFC的包裹容器。

2、在 Block Formatting Context 中,每一個元素左外邊與包含塊的左邊相接觸(對於從右到左的格式化,右外邊接觸右邊), 即使存在浮動也是如此(盡管一個元素的內容區域會由於浮動而壓縮),除非這個元素也創建了一個新的 Block Formatting Context

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呢?

二、如何產生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沒有受浮動的影響,仍然各自占據一行!

三、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>

 

  

效果如下:

四、什么是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

 

五、怎樣觸發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

六、能解決的問題

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都可以解決,可以自己動手試一下,這里就不重復舉例了。

  

 

 

 

  

 

 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM