一、BFC與IFC 1.1、BFC與IFC概要 BFC(Block Formatting Context)即“塊級格式化上下文”, IFC(Inline Formatting Context)即行內格式化上下文。常規流(也稱標準流、普通流)是一個文檔在被顯示時最常見的佈局形態。一個框在常規流中必須屬 ...
一、BFC與IFC
1.1、BFC與IFC概要
BFC(Block Formatting Context)即“塊級格式化上下文”, IFC(Inline Formatting Context)即行內格式化上下文。常規流(也稱標準流、普通流)是一個文檔在被顯示時最常見的佈局形態。一個框在常規流中必須屬於一個格式化上下文,你可以把BFC想象成一個大箱子,箱子外邊的元素將不與箱子內的元素產生作用。
BFC是W3C CSS 2.1 規範中的一個概念,它決定了元素如何對其內容進行定位,以及與其他元素的關係和相互作用。當涉及到可視化佈局的時候,Block Formatting Context提供了一個環境,HTML元素在這個環境中按照一定規則進行佈局。一個環境中的元素不會影響到其它環境中的佈局。比如浮動元素會形成BFC,浮動元素內部子元素的主要受該浮動元素影響,兩個浮動元素之間是互不影響的。也可以說BFC就是一個作用範圍。
在普通流中的 Box(框) 屬於一種 formatting context(格式化上下文) ,類型可以是 block ,或者是 inline ,但不能同時屬於這兩者。並且, Block boxes(塊框) 在 block formatting context(塊格式化上下文) 里格式化, Inline boxes(塊內框) 則在 Inline Formatting Context(行內格式化上下文) 里格式化。
1.2、如何產生BFC
當一個HTML元素滿足下麵條件的任何一點,都可以產生Block Formatting Context:
a)、float的值不為none
b)、overflow的值不為visible
c)、display的值為table-cell, table-caption, inline-block中的任何一個
d)、position的值不為relative和static
CSS3觸發BFC方式則可以簡單描述為:在元素定位非static,relative的情況下觸發,float也是一種定位方式。
1.3、BFC的作用與特點
a)、不和浮動元素重疊,清除外部浮動,阻止浮動元素覆蓋
如果一個浮動元素後面跟著一個非浮動的元素,那麼就會產生一個重疊的現象。常規流(也稱標準流、普通流)是一個文檔在被顯示時最常見的佈局形態,當float不為none時,position為absolute、fixed時元素將脫離標準流。
沒有BFC的情況:
示例代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>BFC與IFC</title> <style type="text/css"> #div1{ width: 200px; height: 200px; background: lightgreen; float: left; } #div2{ width: 300px; height: 300px; background: lightblue; } </style> </head> <body> <h2>BFC與IFC</h2> <div id="div1">div1 </div> <div id="div2">div2 </div> </body> </html>View Code
運行結果:
此時的div1因為float已經產生了BFC,在div2中添加樣式overflow:hidden讓其產生BFC,代碼如下:
#div2{ width: 300px; height: 300px; background: lightblue; overflow: hidden; }
運行結果:
b)、清除元素內部浮動,計算浮動元素的高度
只要把父元素設為BFC就可以清理子元素的浮動了,最常見的用法就是在父元素上設置overflow: hidden樣式,對於IE6加上zoom:1就可以了(IE Haslayout)。
當一個元素的內部元素浮動時不會計算其高度,示例如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>BFC與IFC</title> <style type="text/css"> #div0 { border: 2px solid lightsalmon; padding: 20px; width: 400px; } #div1 { width: 200px; height: 200px; background: lightgreen; float: left; } #div2 { width: 200px; height: 200px; background: lightblue; float: left; } </style> </head> <body> <h2>BFC與IFC</h2> <div id="div0"> <div id="div1">div1 </div> <div id="div2">div2 </div> </div> </body> </html>View Code
運行結果:
修改div0讓其觸發BFC,還原高度,代碼如下:
#div0 { border: 2px solid lightsalmon; padding: 20px; width: 400px; overflow: hidden; /*讓div0觸發BFC*/ }
運行結果:
c)、外邊距將不再與上下文之外的元素摺疊
示例代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>BFC與IFC</title> <style type="text/css"> #div1 { width: 200px; height: 200px; background: lightgreen; margin-bottom: 100px; } #div2 { width: 200px; height: 200px; background: lightblue; margin-top: 100px; } </style> </head> <body> <h2>BFC與IFC</h2> <div id="div1">div1 </div> <div id="div2">div2 </div> </body> </html>View Code
如果此時將腳本的div1與div2同時變成BFC環境,修改的css如下:
#div1 { width: 200px; height: 200px; background: lightgreen; margin-bottom: 100px; overflow: hidden; } #div2 { width: 200px; height: 200px; background: lightblue; margin-top: 100px; overflow: hidden; }
執行時會發現效果還是一樣,此時的div1與div2都是BFC上下文,但是要求的是:外邊距將不再與上下文之外的元素摺疊,按照要求,我們應該將div1與div2放在不同的上下文中,修改後的腳本如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>BFC與IFC</title> <style type="text/css"> #div1 { width: 200px; height: 200px; background: lightgreen; margin-bottom: 100px; } #div2 { width: 200px; height: 200px; background: lightblue; margin-top: 100px; } #div2-outer { overflow: hidden; } </style> </head> <body> <h2>BFC與IFC</h2> <div id="div1">div1 </div> <div id="div2-outer"> <div id="div2">div2 </div> </div> </body> </html>
運行結果如下:
d)、元素會一個接一個地被垂直放置,它們的起點是一個包含塊的頂部(文字不會環繞佈局)
示例代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>BFC</title> <style> .div1 { border: 3px solid blue; width: 300px; } .cls1 { width: 100px; height: 100px; background: lightblue; margin: 5px; float:left; } </style> </head> <body> <div class="div1"> <div id="div11" class="cls1">div11</div> <p> 扁粉菜(BFC)是安陽名吃,製作原料和工藝都很簡單。扁粉菜是大鍋菜,以扁粉條為主原料;熬一大鍋的高湯,將扁粉條下鍋煮熟,再燴入豆腐片,豬血片和青菜。盛上一碗加點辣椒,配上熱乎乎的油餅,吃上一口,怎一個“爽”字了得!扁粉菜最有營養的算是高湯和豬血片了,而且可以續湯,雖然它是粗食,但是便宜,實惠,營養,所以大家都愛吃 </p> </div> </body> </html>View Code
沒有BFC時的運行結果:
從運行結果可以看出div與p還是重疊了,只是文字被擠出,和前面提到的重疊是同一個意思,將p元素觸發BFC後的效果如下圖所示:
p{ overflow: hidden; }
運行結果:
1.4、IE與Layout
Layout是 IE 瀏覽器渲染引擎的一個組成部分。在 IE 瀏覽器中,一個元素要麼自己對自身的內容進行組織和計算大小, 要麼依賴於包含塊來計算尺寸和組織內容,hasLayout 與 BFC 有很多相似之處。在IE中,元素使用“佈局”概念來控制尺寸和定位,分為擁有佈局和沒有佈局兩種情況,擁有佈局的元素由它控制本身及其子元素的尺寸和定位,而沒有佈局的元素則通過父元素(最近的擁有佈局的祖先元素)來控制尺寸和定位,而一個元素是否擁有佈局則由 hasLayout 屬性告知瀏覽器,它是個布爾型變數,true 代表元素擁有佈局,false 代表元素沒有佈局。簡而言之,hasLayout 只是一個 IE 下專有的屬性,hasLayout 為 true 的元素瀏覽器會賦予它一系列的效果。
特別註意的是,hasLayout 在 IE 8 及之後的 IE 版本中已經被拋棄,所以在實際開發中只需針對 IE 8 以下的瀏覽器為某些元素觸發 hasLayout。
出發IE下的haslayout方法:
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
綜合前面的內容清除浮動的寫法如下:
.floatfix{ *zoom:1; /*在舊版本的IE瀏覽器縮放大小,觸發haslayout*/ } .floatfix:after{ content:""; display:table; clear:both; }
除了BFC還有IFC,GFC,FFC,是不同格式化上下文(Formatting Context)的簡稱,GFC是網格格式化上下文(Grid Formatting Context),FFC是彈性盒格式化上下文(Flex Formatting Context),FKC是開封菜的意思:)。
二、定位
使用css佈局position非常重要,他的語法如下:
position:static | relative | absolute | fixed | center | page | sticky
預設值:static,center、page、sticky是CSS3中新增加的值。
2.1、static
可以認為靜態的,預設元素都是靜態的定位,對象遵循常規流。此時4個定位偏移屬性不會被應用,也就是使用left,right,bottom,top將不會生效。
示例:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>定位</title> <style type="text/css"> #div1{ width: 200px; height: 200px; background: lightblue; left:100px; top:100px; } </style> </head> <body> <div id="div1"> </div> </body> </html>View Code
運行結果:
定義偏移並未起作用。
2.2、relative
相對定位,對象遵循常規流,並且參照自身在常規流中的位置通過top,right,bottom,left這4個定位偏移屬性進行偏移時不會影響常規流中的任何元素。
示例代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>相對定位</title> <style type="text/css"> div { width: 200px; height: 200px; background: lightblue; margin: 10px; } #div1 { position: relative; /*相對定位*/ left:30px; /*在自己原有位置上相對左邊偏移30像素*/ bottom: -30px; background: lightgreen; } </style> </head> <body> <div id="div1">div1 </div> <div id="div2">div2 </div> </body> </html>
運行結果:
2.3、absolute
絕對定位,對象脫離常規流,此時偏移屬性參照的是離自身最近的定位祖先元素,如果沒有定位的祖先元素,則一直回溯到body元素。盒子的偏移位置不影響常規流中的任何元素,其margin不與其他任何margin摺疊。
元素定位參考的是離自身最近的定位祖先元素,要滿足兩個條件,第一個是自己的祖先元素,可以是父元素也可以是父元素的父元素,一直找,如果沒有則選擇body為對照對象。第二個條件是要求祖先元素必須定位,通俗說就是position的屬性值為非static都行。
示例代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>絕對定位</title> <style type="text/css"> div { border: 2px solid darkturquoise; padding: 10px; } #div1 { width: 400px; height: 400px; } #div2 { width: 300px; height: 300px; } #div3 { width: 200px; height: 200px; position: absolute; right: 5px; top: 5px; } </style> </head> <body> <div id="div1"> div1 <div id="div2"> div2 <div id="div3">div3 </div> </div> </div> </body> </html>
運行結果:
因為div3使用absolute絕對定位,它的參考對象是父元素div2,div1都不滿足條件,因為兩者都沒有進行定位,是預設的定位值static,根據約定最終找到body,所以會出現在頁面的右上角。此時如果想讓div3的參照對象為div1,則可以修改代碼為:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>絕對定位</title> <style type="text/css"> div { border: 2px solid darkturquoise; padding: 10px; } #div1 { width: 400px; height: 400px; position: relative; /*相對定位*/ } #div2 { width: 300px; height: 300px; } #div3 { width: 200px; height: 200px; position: absolute; right: 5px; bottom: 5px; } </style> </head> <body> <div id="div1"> div1 <div id="div2"> div2 <div id="div3">div3 </div> </div> </div> </body> </html>