看了不少關於BFC的文章,就總結一下。終於應該算是明白了!
其實要說BFC,就要說普通流(normal flow),就要說IFC(內聯格式化上下文),在一起都說了,才能講的明白。
普通流說白了就是怎樣把文檔中的元素等自上而下一個一個的呈現出來,這些元素怎么在頁面中擺放,而這個呈現過程就是普通流
那么普通流是怎么樣把頁面布局呈現的呢?就是通過BFC和IFC,還有一個relative positioning(相對位移),今天重點講解BFC和IFC
BFC名字很高大上,說白了就是一個規則,這個規則應用於塊級元素(div,p)上。
IFC這個規則應用於內聯元素(span,em,i)上。
在文檔呈現開始的時候,會自動創建一個BFC和IFC,來對整個頁面進行布局,在沒有我們通過設置一些屬性,來創建一個新的BFC的時候,整個文檔就這一個BFC和IFC,所以所有的元素都要使用這個規則。
在普通流中,所有的盒子(不管是內聯盒子(內聯元素等)還是塊級盒子(塊級元素等))都要屬於一個格式化上下文,不是屬於塊級格式化上下文就是屬於內聯格式化上下文,但是不能同時屬於兩者,塊級元素布局遵循塊級格式化上下文的規則,內聯元素布局遵循內聯格式化上下文的規則來進行布局.就是這兩個規則使得頁面的所有元素有序的布局,才呈現出我們所看到的web頁面。
什么是BFC,IFC
BFC,IFC,就是控制元素如何進行布局。
BFC規則:
1.如果給一個元素創建了一個BFC,就相當於創建了一個新的容器,容器內和容器外中的元素不會相互影響。外邊的BFC規則,不會對容器里的BFC產生影響,而容器里面的BFC也不會對容器外的BFC產生影響,也就是相互隔絕,互不影響。
2.盒子的布局開始是從包含容器的頂部開始的。
3.同一個BFC中,在兩個相鄰的塊級元素中,垂直margin會發生折疊
4.每個盒子的左邊界都要緊靠包含容器的左邊界(這也就解釋了為什么塊級元素都是單獨成一行的,如果不單獨成行,第二個盒子的左邊界怎么緊靠包含容器的左邊界);
這第四個是最重要的布局規則
IFC規則:
1.盒子是水平一個接一個的排列,水平的margin,內邊距,邊框是可以有的。
2.垂直方向的對齊,可能是底部對齊,頂部對齊,也可能是基線對齊(這個是默認的);ps.這里的盒子應該是指的內聯元素的盒子(span,strong等)和匿名內聯盒子(只有文本,沒有內聯元素包含,自動創建的),他們合稱內聯盒子,一個或者多個內聯盒子組成一個行框,行框的寬度由包含塊和出現的浮動決定的(為什么有浮動呢,后面解釋);行框的高度決定看我的這篇文章(css之line-height);一定要分清楚,行框和內聯盒子的關系,要不然我所說的你就不太可能理解
3.行框中的內聯盒子的高度小於行框的高度時,內聯盒子的垂直方向的對齊方式取決於vertical-align屬性
4.當一個行框水平不能容納內聯盒子時,他們將會在垂直方向上產生多個行框,他們上下一個挨着一個,但是不會重疊
5.一般來說,行框的左邊界緊挨着包含容器的左邊界,行框的右邊界緊挨着包含容器的右邊界,(是兩個邊都緊挨着)。然而,浮動盒子可能存在於包含邊框邊界和行框邊界之間(后面解釋這種情況);
6.多個內聯盒子的寬度小於包含他們的行框時,他們在水平方向的分布取決於text-align屬性(默認是left)
能產生新的BFC的屬性:
1.float的值不為none。
2. overflow的值不為visible。
3.display的值為table-cell, table-caption, inline-block中的任何一個。
4.position的值不為relative和static。
只要給元素設置這些屬性,則這些元素容器就不受外面的BFC約束了,他會給自己和他包含的元素應用新的BFC。也就是現在這些BFC平起平坐,你管不着我,我管不着你,只是我們兩個的BFC規則是一樣的。
如果你上面這些沒有看懂的話,通過代碼一定能看懂。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> <style> body,div{ margin:0; padding:0; } #box1,#box2,#box3{ width:100px; height:110px; border: 1px solid red; } #box4{ width:500px; border:1px solid red; height:100px; } #box4Child{ width:100px; height: 50px; border: 1px solid black; float:left; } </style> </head> <body> <div id="box1"></div> <div id="box2"></div> <div id="box3"> <span>我是內聯元素盒子</span>我是內聯匿名元素盒子<em>我也是內聯元素盒子</em> </div> <div id="box4"><div id="box4Child"></div><span>我是內聯元素盒子</span>我是內聯匿名元素盒子<em>我也是內聯元素盒子</em></div> </body> </html>
文檔解析我就從body開始說起,我就形象一點說,
1.當普通流遇見body元素時,一看你是塊級元素,應用BFC規則,所以,你要從你包含容器html元素頂部開始,左邊緊靠他的左邊,於是body就布局好了
2.接下來就是body里面的的box1了,普通流一看,你也是塊級元素,你也要應用BFC規則,因為你是第一個body的第一個元素,所以從body容器的頂部開始布局,你的左邊也要緊靠body的左邊,並且你后面的元素要距離你10px,於是乎,box1就布局好了
3.box2開始了,box2跟普通流說你看box1寬度才100px,你讓我在他后面吧,我們兩個在一行才200px,普通流說不行,BFC的規則是你的左邊必須緊靠包含容器(body元素)的左邊,於是乎box2就只能自己一行了,(這也就是解釋了為什么塊級元素單獨成行),普通流說你看你的margin-top和box1的margin-bottom是相鄰的,根據BFC你們必須折疊,於是他們兩個之間的距離就10px,而不是20px;
4.同理,box3跟類似上面的,於是box3就布局好了;
5.現在進行box3的內部了,IFC說,span是內聯元素應該應用我的規則,我先創建一個行框(行框是他的左邊挨着包含框的左邊,右邊挨着包含框的右邊),這時發現一個行框太小,不能包含的了這個內聯盒子,於是,就在下面又創建了一個行框,來包含這個內聯盒子。這次兩個行框終於把span內聯盒子裝下了,接下來是又是一個盒子,這次是個匿名內聯盒子,既然都是內聯的,就挨着span內聯盒子繼續吧,發現也是放不下,就又創建了一個內聯盒子,下面的em也是那樣我就不說了,balabala。
6. 接下來開始布局box4,一看是塊級元素就使用BFC。
7. 進行box4內部布局,一看是塊級元素但是呢她又有float屬性,這是就創建一個新的BFC,這時就不受BFC規則的約束了。就不需要獨占一行等規則了,但是呢,這又牽扯到float布局定位機制,float的一些特性,float是這樣的,比如設置左浮動,那么它的左邊一定要緊挨着包含元素的左邊或者是另一個浮動元素的右邊。多了我就不說了,看官方文檔。這時box4child就布局好了,接下來就布局后面的東西了,一看是一個內聯元素,好吧,就創建一個行框,這時要注意了上面IFC規則的第五條的后半部分,也就是說,現在在這里,這個行框的左邊界不在緊挨着包含塊的左邊界了他也是可以挨着浮動元素的邊界的,於是就產生了圖中的效果,后面的東西同理上面就不多說了。
僅僅是個人理解,如有不對歡迎指正交流!
ps。之前寫了一個爬取指定網站的算是小爬蟲吧,使用nodejs寫的,里面我添加了爬取博客園,csdn的關於web的版塊,segmentfault問答,segmentfault文章,百度貼吧的JavaScript吧,w3ctech,w3cfuns等,我也就常去這幾個網站了。界面我就以簡潔為主。現在我就一直使用它來看文章,主要是簡單快捷方便;地址:小爬蟲