更好閱讀體驗移步:zhangzippo.github.io/posts/2019/…css
BFC(格式化上下文)在整個css體系中是比較重要的概念,也牽扯了不少其餘問題好比如浮動、定位、盒模型等,這篇文章主要幫助理解bfc的概念,特性和應用場景。html
先看一段來自MDN的定義:git
塊格式化上下文(Block Formatting Context,BFC) 是Web頁面的可視化CSS渲染的一部分,是塊盒子的佈局過程發生的區域,也是浮動元素與其餘元素交互的區域。github
嗯,很是嚴謹且官方(就是看不懂)那麼我嘗試用一種便於理解的方式來解釋這個BFC,你能夠簡單的理解BFC就是頁面上的一起區域,這個區域有一些特性,而且該區域內部有一套本身的規則不對外界元素產生干擾,是一塊相對獨立的渲染區域。(注意,參與BFC的是塊盒子)瀏覽器
參考其餘博客中我認爲最貼切的解釋: 塊格式上下文是頁面CSS 視覺渲染的一部分,用於決定塊盒子的佈局及浮動相互影響範圍的一個區域。bash
產生這塊區域須要知足如下幾種條件:ide
- 根元素或包含根元素的元素
- 浮動元素(元素的
float
不是none
)- 絕對定位元素(元素的
position
爲absolute
或fixed
)- 行內塊元素(元素的
display
爲inline-block
)overflow
值不爲visible
的塊元素display
值爲flow-root
的元素- 表格單元格(元素的
display
爲table-cell
,HTML表格單元格默認爲該值)- 表格標題(元素的
display
爲table-caption
,HTML表格標題默認爲該值)- 匿名錶格單元格元素(元素的
display
爲table
、table-row
、table-row-group
、table-header-group
、table-footer-group
(分別是HTML table、row、tbody、thead、tfoot的默認屬性)或inline-table
)contain
值爲layout
、content
或strict
的元素- 彈性元素(
display
爲flex
或inline-flex
元素的直接子元素)- 網格元素(
display
爲grid
或inline-grid
元素的直接子元素)- 多列容器(元素的
column-count
不爲auto
,包括column-count
爲1
)column-span
爲all
的元素始終會建立一個新的BFC,即便該元素沒有包裹在一個多列容器中。
能夠看出有不少觸發BFC區域的條件,其中前幾個斜粗體的描述是咱們常常遇到也須要重點記住的,後面的幾種能夠看成擴展瞭解就好。佈局
這裏重點說一下display:flow-root,display:flow-root是什麼意思呢?它能夠建立無反作用的BFC。在父級塊中使用 display: flow-root 能夠建立新的BFC。咱們剛纔分析了上面幾種創造bfc的方式,但他們都是有反作用的(好比float會讓元素脫離文檔流靠左或靠右,position的絕對定位也會脫離文檔流,overflow的值也會形成一些額外的影響),而這個值的設定是單純創造一個BFC,沒有任何其餘影響,可是這個屬性目前瀏覽器支持的不是很好,下圖是這個值的兼容狀況: post
這裏引用MDN的解釋:flex
塊格式化上下文包含建立它的元素內部的全部內容,但不包括建立了新BFC的子元素的內部元素。 塊格式化上下文對浮動定位與清除浮動都很重要。浮動定位和清除浮動時只會應用於同一個BFC內的元素。浮動不會影響其它BFC中元素的佈局,而清除浮動只能清除同一BFC中在它前面的元素的浮動。外邊距摺疊也只會發生在屬於同一BFC的塊級元素之間。 這段話的重點在於1:BFC將影響內部包含的全部內容,除非內部建立了新的子BFC區域;2:全部的BFC影響只會發生在同級次的BFC區域中。
以下面的代碼,box建立了一個BFC區域,那麼將影響son_1,son_1-1,son_2,因爲son_本身建立了一個BFC區域,所以son_2-1將不受box的BFC影響,而只受son_2的BFC影響
<div id='box' class='BFC'>
<div id='son_1'>
<div id='son_1-1'></div>
</div>
<div id='son_2' class='BFC'>
<div id='son_2-1'></div>
</div>
</div>
複製代碼
從下圖我門能夠看到,外層盒子創造了一起BFC區域會清除浮動,第一層由於浮動的關係撐開了外層盒子,因爲float:left創造了一起新的BFC區域,所以它的子元素的float不會撐開最外層,所以沒有受到最外層BFC的影響(沒有撐開第二層由於第二層給了固定高度)。這更佳說明了BFC是一塊獨立區域,而且內部不會影響BFC外部元素的特性。
關於如下特性介紹在css2.1規範的文檔中(文章結尾文獻)有相關介紹,這裏前幾條是翻譯過來說,後面幾條是來自其餘文章的總結。
特性1:在BFC中,內部塊(block塊級元素)從頂部開始依次垂直排列。兩個同級塊之間的垂直距離由「Margin」屬性肯定。
這個特性沒什麼說的,就是在BFC區域內部的子塊級元素會垂直排列,這點即便不在BFC內其實也是同樣的,多個div會在容器內部垂直的一個一個排列。
特性2: 內部塊垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊。
這個特性是指相鄰的兩個子塊元素的相隔距離由margin決定,但並非margin的和,而是會重疊(實際就是是margin之間的最大值),以下代碼:
<div class="box">
<div class="son">
I am one
</div>
<div class="son">
I am two
</div>
<div class="son">
I am three
</div>
</div>
<style> .box { background-color: rgb(224, 206, 247); display:flow-root; // 創造一個BFC區域 width:100%; } .son { width: 200px; height: 150px; background-color: white; border: 1px solid black; padding: 10px; margin:10px 0; } .son:last-child{ margin:20px 0; } </style>
複製代碼
效果以下:
能夠看到每一個元素之間的margin是10像素,而最後一個box與上方的box之間是20,由於margin的重疊致使了取的是兩個相鄰box的最大值。
特性3:每一個子塊元素的左外邊緣接觸包含塊的左邊緣(對於從右到左的格式,右邊緣接觸)。即便在存在浮動的狀況下也是如此。
這裏解釋一下,咱們知道每個box模型是由四個層級構成的,如圖:
.box {
background-color: rgb(224, 206, 247);
border: 5px solid rebeccapurple;
display:flow-root;
padding: 10px;
}
.float {
float:left; // 添加浮動
width: 200px;
height: 150px;
background-color: white;
border: 1px solid black;
margin:0 10px;
}
複製代碼
內部元素有一個10像素的margin,外部盒子有10像素的padding,內部元素的margin-box的左邊與包含塊content-box的作邊緣接觸
特性4:BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素,反之亦然; 這點在上面咱們介紹影響範圍的時候介紹過,再也不作過多說明了。
特性5:計算BFC的高度時,考慮BFC所包含的全部元素,連浮動元素也參與計算 這個特性就是爲什麼子元素浮動,若是要清除浮動能夠在父元素上創造一個bfc的解釋,這樣高度就囊括了浮動元素。 特性6:浮動盒區域不疊加到BFC上
<div class="box"></div>
<div class="float"></div>
<style>
.box {
background-color: rgb(224, 206, 247);
border: 5px solid rebeccapurple;
height:100px;
width:100px;
padding:10px; display:flow-root;
}
.float {
float:left;
height: 150px;
background-color: white;
border: 1px solid black;
padding: 10px;
}
</style>
能夠看到浮動元素沒有覆蓋到bfc上面
複製代碼
1. 分屬於不一樣的BFC時能夠阻止margin重疊 根據特性2咱們知道,BFC內的元素排列時margin會重疊,所以咱們爲了防止重疊,可使兩個元素建立本身的bfc,這樣margin就不會重疊。 2. 能夠包含浮動元素——清除內部浮動 根據特性五能夠得知。 3. 能夠阻止元素被浮動元素覆蓋 根據特性六,只須要將被覆蓋的元素建立成爲BFC就能夠解決這個問題。 4. 自適應兩欄佈局 咱們能夠利用bfc的特性來構造兩欄佈局:
<div class="left"></div>
<div class="right"></div>
<style>
.left{
background:yellow;
width:200px;
height:400px;
float:left;
}
.right{
background:pink;
height:400px;
/*添加overflow:hidden,觸發元素BFC*/
overflow:hidden;
}
</style>
複製代碼
這篇文章對BFC的前置概念沒有過多說明,好比盒模型以及定位方案等,能夠查看juejin.im/post/59b73d…這篇文章,本篇文章也部分參考了該文章。
developer.mozilla.org/zh-CN/docs/… www.w3.org/TR/CSS21/vi… juejin.im/post/59b73d…