我們在前端的學習過程中常常會遇到BFC,用BFC來解決一些margin塌陷、margin合並清理浮動流的問題
那么問題來了,我們所說的BFC到底是個什么東西呢;
什么是BFC
BFC(Block Formatting Context)即“塊級格式化上下文。我來簡單的解讀一下:
1.塊級對應單詞Block,不難想到的就是display中block屬性,block屬性是將此元素作為塊級元素顯示,根據塊級元素的特性進行渲染,具體的特性下文再來細說。
2.格式化Formatting,格式化這個此相信不用我細說,就是回歸元素最原始的狀態,即剛開始被定義時的狀態。
3.上下文Content我們很熟悉,在js中上下文是一個函數執行前被定義好的的一個環境,是外部數據的集合。在這里好像還是有一點點聯系的。
綜合在一起就是:我們在定義塊級元素,塊級元素在剛剛被生成的時候(即初始化)需要規定一些規則來在瀏覽器上布局顯示這個塊級元素,這些規則也就塊級元素所處的環境將成為塊級元素與其他元素之間的特性。
簡單來說,就是你是塊級元素,瀏覽器在布局時有自己一套對塊級元素布局的規則,身為塊級元素你得按照我(瀏覽器)的規矩來。
那么為什么在我們在布局的時候會出現一些我們不期望的結果(如浮動脫離文檔流和margin合並的問題)
慢慢來,首先就要說說BFC布局的規則是什么以及普通文檔在布局是的規則又是什么?
普通文檔流布局規則
1.浮動的元素是不會被父級計算高度
2.非浮動元素會覆蓋浮動元素的位置
3.margin會傳遞給父級
4.兩個相鄰元素上下margin會重疊
BFC布局規則
1.浮動的元素會被父級計算高度(父級觸發了BFC)
2.非浮動元素不會覆蓋浮動元素位置(非浮動元素觸發了BFC)
3.margin不會傳遞給父級(父級觸發了BFC)
4.兩個相鄰元素上下margin會重疊(給其中一個元素增加一個父級,然后讓他的父級觸發BFC)
轉自:https://www.cnblogs.com/CafeMing/p/6252286.html
定位方案是控制元素的布局,常見的有三種:
普通流(normal flow)
其實就是元素按照再HTML中的先后位置之上而下布局,在這個過程中,行內元素水平排列,直到當行被沾滿然后換行,塊級元素則會被渲染為完整的一個新行,除非另外制定,否則所有元素默認都是普通流定位,也可以說,普通六中元素的位置由該元素再HTML文檔中的位置決定。
浮動(float)
在浮動布局中,元素首先按照普通流的位置出現,然后根據浮動的方向盡可能地向左邊或右邊偏移,其效果與印刷排版中的文本環繞相似。
絕對定位(absolute positioning)
在絕對定位布局中,元素會整體脫離普通六,因此絕對定位元素不會對其兄弟元素造成影響,而元素具體的位置由絕對定位的坐標決定。
BFC 布局規則
內部的Box會在垂直方向,一個接一個地放置。
Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊
每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,否則相反)。即使存在浮動也是如此。
BFC的區域不會與float box重疊。
BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。反之也如此。
計算BFC的高度時,浮動元素也參與計算
轉自:https://blog.csdn.net/AmberWu/article/details/79543896
以上是我看的兩個對流布局的理解(網上特別多,說法各有不同各有千秋)
如何觸發BFC
只要元素滿足下面任一條件即可觸發BFC特性:
body根元素
浮動元素:float除none以外的值
絕對定位元素:position(absolute、fixed)
display為inline-block、table-cells、flex
overflow除了visible以外的值(hidden、auto、scroll)
用BFC來解決布局上的一些問題
1.margin合並
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ margin: 0; padding: 0; } .top{ width: 100px; height: 100px; background: #f00; margin-bottom:100px; } .bottom{ width: 100px; height: 100px; background: #0ff; margin-top: 200px; } </style> </head> <body> <div class="top"></div> <div class="bottom"></div> </body> </html>
可以看到兩方塊的上下margin只有200px,按照代碼來說應該是上面的100加上下面的200,最后值為300px才對,上面的margin-bottom的100px與下面margin-top重疊了,出現了margin合並
問題出現的原因:兩個塊級元素處在同一個BFC環境下,同一BFC環境下的子元素margin上下會互相影響(這其實就是個bug,到我發稿為止還沒完善)
解決辦法:將兩個元素放到不同的BFC環境下就好了,如把第二個方法bottom放到另一個bfc容器內,top中的margin-bottom是在A BFC(body)環境下的,而bottom中的margin-top實在B BFC(box)環境下的,每一個BFC都是獨立的,BFC內部元素的布局不會對外部造成影響,這樣一來問題就解決了。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ margin: 0; padding: 0; } .top{ width: 100px; height: 100px; background: #f00; margin-bottom:100px; } .box{ overflow: hidden;/*bfc*/ } .bottom{ width: 100px; height: 100px; background: #0ff; margin-top: 200px; } </style> </head> <body> <div class="top"></div> <div class="box"> <div class="bottom"></div> </div> </body> </html>
2.margin塌陷
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ margin: 0; padding: 0; } .outer{ width: 200px; height: 200px; background: red; margin-top: 100px; } .inner{ width: 50px; height: 50px; background: blue; margin-top:50px; } </style> </head> <body> <div class="outer"> <div class="inner"></div> </div> </body> </html>
我們想要的效果是inner盒子距離outer盒子上邊距有一個50px的margin,但是實際情況是inner的margin與outer的margin重疊了,原理上與margin合並一樣。
出現的原因:兩個盒子處於同一個BFC環境下
解決方法:讓outer盒子變成BFC元素,讓里面inner單獨處於一個BFC環境
.outer{ width: 200px; height: 200px; background: red; margin-top: 100px; overflow: hidden; }
3.清除浮動流
最常見的情況就是用一個div來包裹浮動元素
有浮動流的情況下下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ margin: 0; padding: 0; } .outer{ border: 2px solid black; margin:100px; } .inner{ width: 100px; height: 100px; float: left; } .red{ background: red; } .green{ background: green; } .blue{ background: blue; } </style> </head> <body> <div class="outer"> <div class="inner red"></div> <div class="inner green"></div> <div class="inner blue"></div> </div> </body> </html>
可以看的的是外面的outer並沒有被內容所撐開
為什么會出現這樣的情況呢
首先要先說一下什么是浮動流:浮動流是浮動元素的一種布局方式,浮動讓行內元素或塊元素自動轉化為行內塊元素。
浮動元素會脫離當前的文檔流,后面出現的非浮動元素在排版時還是會按照原來的文檔流來排版,所以會出現浮動元素和正常元素重疊的情況。
浮動元素脫離的只是當前的文檔流,在給父級outer加margin的時候浮動元素也會跟着父級移動。
float屬性在一開始的時候是為了報紙排版才產生的,所以文本類的元素能夠感知到浮動流,並在浮動元素的周圍排列形成文字環繞。
出現問題的原因:浮動元素處於浮動流,與普通元素所處的流層不一致,所以布局排版時是按照兩個規則來布局的
解決方法:整個放到一個BFC環境下,使用同一個規則。只想要float的特性,不想要浮動流對布局的影響。
.outer{ border: 2px solid black; margin:100px; overflow: hidden; }
以上就是我對BFC的認識和對浮動流的理解,如何有什么錯的地方或者是問題歡迎大家一起來討論