前言
本文包括以下內(nèi)容:
- 什么是BFC
- 如何產(chǎn)生BFC
- BFC的特點
- 應(yīng)用BFC
1、什么是BFC
BFC (Block formatting contexts)塊級格式化上下文旺韭,首先看一下 w3c 是如何定義BFC的(大致翻譯如下):
浮動元素,絕對定位元素,非塊級盒子的塊級容器(例如 inline-blocks, table-cells, 和 table-captions)牺弹,以及
overflow
不為 visiable 的塊級盒子,都會為他們的內(nèi)容創(chuàng)建新的塊級格式化上下文。
在一個塊級格式化上下文中蹦骑,盒子從頂端開始垂直地一個接一個地排列,兩個盒子之間的垂直的間隙是由他們的margin 值所決定的臀防。在一個BFC中眠菇,兩個相鄰的塊級盒子的垂直外邊距會產(chǎn)生合并边败。
在塊級格式化上下文中,每一個盒子的左外邊緣(margin-left)會觸碰到容器的左邊緣(border-left)(對于從右到左的格式來說捎废,則觸碰到右邊緣)放闺,即使存在浮動也是如此,除非這個盒子創(chuàng)建一個新的塊級格式化上下文缕坎。
可以這樣理解BFC:把BFC看作一個盒子(容器),這個BFC盒子有自己獨立的布局方式篡悟,一個BFC盒子中的元素布局不受外界影響谜叹,也不會影響到外面的元素。且在一個BFC中塊盒與行盒都會垂直排列搬葬,若存在外邊距則會產(chǎn)生外邊距合并荷腊。
2、如何產(chǎn)生BFC
在怎樣的條件下會產(chǎn)生塊級格式化上下文急凰,這里引用部分 MDN關(guān)于BFC 的內(nèi)容女仰。
- 浮動元素
- 絕對定位的元素 (元素具有position為 absolute或 fixed)
- 內(nèi)聯(lián)塊 inline-blocks (元素具有 display: inline-block)
- 表格單元格 、標題(元素具有 display: table-cell抡锈、table-caption疾忍,HTML表格單元格默認屬性)
- 塊元素具有
overflow
且值不是 visible的
3、BFC的特點
- 同屬一個BFC的內(nèi)容會發(fā)生外邊距合并(Margin Collapse)床三,兩個外邊距大致可以分為下列三種情況:
- 外邊距均為正值一罩,取兩者中較大的數(shù)
- 外邊距一正一負時,取兩者相加
- 外邊距均為負時撇簿,取兩者中絕對值較大的
- BFC不會重疊浮動元素
- BFC可以包含浮動
4聂渊、應(yīng)用BFC
- 解決外邊距合并的問題。
同屬一個BFC的內(nèi)容會發(fā)生外邊距合并四瘫,那么汉嗽,我們可以建立新的BFC,使得它們不屬于同一個BFC時則外邊距不會發(fā)生合并找蜜。
先是相鄰的兄弟元素外邊距合并饼暑,需要先給其中的一個盒子加上一個父元素,然后給這個父元素添加overflow:hidden
锹杈,這一點很重要撵孤,可以理解為這個屬性是為其中的content
新創(chuàng)建一個BFC,所以一開始在創(chuàng)建這個Demo的時候 我就有類似這樣的疑問:overflow:hidden 能觸發(fā)BFC竭望,為什么不會阻止垂直外邊距疊加邪码?
其實解決外邊距合并的方法其實有很多,個人覺得用BFC并不好咬清,且麻煩闭专,需要先創(chuàng)建一個父元素(因為直接給子元素.box2
設(shè)置overflow: hidden
是無效的)奴潘。當我嘗試使用另外一個方法:display: inline-block
創(chuàng)建BFC的時候,發(fā)現(xiàn)并不需要創(chuàng)建父元素影钉,外邊距會直接合并画髓。
這時候我就遇到了這樣一個問題: 同樣是創(chuàng)建BFC,為什么使用overflow: hidden
需要創(chuàng)建父元素平委,而使用display: inline-block
不需要創(chuàng)建父元素呢奈虾?
個人理解是這樣的:這些應(yīng)用BFC的屬性,為它們的content
創(chuàng)建了一個新的獨立計算區(qū)域(BFC)廉赔,在這塊新的獨立計算區(qū)域中與外面元素的外邊距不產(chǎn)生重疊肉微,而在這塊獨立計算區(qū)域之內(nèi)仍然是外邊距重疊的。
而當使用display: inline-block
觸發(fā)了別的外邊距合并的條件(可能是因為 IFC)蜡塌,并非因為BFC而發(fā)生合并碉纳。在下面的參考文章鏈接中也有指出那么一點:
inline-block元素不與任何元素的外邊距產(chǎn)生折疊
還可以參照下圖,可知應(yīng)該是display: inline-block
的問題使得外邊距計算直接相加馏艾,當我們再使用其它屬性劳曹,如display: table-cell
的時候,仍然需要為這個元素創(chuàng)建父元素div.ct
然后應(yīng)用屬性,產(chǎn)生BFC才可以生效琅摩,而直接用在相鄰元素上是無效的铁孵。
-
實現(xiàn)兩欄布局 及 去除文字環(huán)繞效果
當存在兩個相鄰的div
時,它們會垂直排列房资,但當給第一個元素設(shè)置float
屬性時库菲,則會發(fā)生盒子重疊。假設(shè)第一個盒子比第二個盒子大(否則覆蓋后就看不到第二個盒子)志膀。在這里會首先發(fā)現(xiàn)這個文字并不會被浮動元素遮擋(現(xiàn)在是文字較少的情況熙宇,僅4個字符),當box1
大于box2
時溉浙,這個文字仍然不會被遮擋而是跑到盒子的右側(cè)或下側(cè)(據(jù)box2
寬高決定)烫止。
當文字較多時,所有的文字都會圍繞著box1
戳稽,形成文字環(huán)繞效果馆蠕。而給box2
添加overflow:hidden;
時則不會再發(fā)生文字環(huán)繞。這是之前提到的BFC特性當中的一點: * BFC 不會重疊浮動元素 *惊奇,當給box2
添加屬性時互躬,它就產(chǎn)生了新的BFC使得它不會再去重疊浮動的box1
同理,當去除box2
的寬度時颂郎,即可形成自適應(yīng)的兩欄布局吼渡。
-
解決因為子元素浮動而帶來的父容器高度塌陷問題
當一個父容器中的元素都設(shè)置為浮動,且自身沒有設(shè)置高度時乓序,則父容器的高度就會發(fā)生塌陷(就好像沒有了子元素一樣)寺酪。如下圖中的 ① 過程坎背。而給父元素設(shè)置了overflow: hidden;
時則又發(fā)生了 ② 過程這樣的變化。這是因為這給父容器設(shè)置成了一個新的BFC寄雀,再結(jié)合之前的特性:BFC可以包含浮動 可知得滤,就是因為這個BFC的生成使得高度不塌陷。(使用其它屬性如display: table-cell
也可使得高度不塌陷)
后記
使用BFC并不是很好的解決方案盒犹,像一個外邊距合并問題給人帶來的困擾就非常大懂更,完全可以使用更簡單的方案 如給父元素添加透明的border
或padding
來解決; 像是兩欄布局以及去除文字環(huán)繞效果急膀,也可以通過margin-left
來解決膜蛔,使用overflow: hidden
也會產(chǎn)生新的問題,如文字溢出無法顯示脖阵;最后一個更是可以使用清除浮動(添加.clearfix
)來解決父元素高度塌陷。
這里使用BFC 僅僅是為了更好理解它而已 ~