一婉弹、常見(jiàn)定位方案
了解 BFC 之前睬魂,我們先來(lái)了解一下常見(jiàn)的定位方案,定位方案是控制元素的布局镀赌,有三種常見(jiàn)方案:
- 普通流 (normal flow)
在普通流中氯哮,元素按照其在 HTML 中的先后位置至上而下布局,在這個(gè)過(guò)程中商佛,行內(nèi)元素水平排列喉钢,直到當(dāng)行被占滿然后換行,塊級(jí)元素則會(huì)被渲染為完整的一個(gè)新行威彰,除非另外指定出牧,否則所有元素默認(rèn)都是普通流定位,也可以說(shuō)歇盼,普通流中元素的位置由該元素在 HTML 文檔中的位置決定舔痕。 - 浮動(dòng) (float)
在浮動(dòng)布局中,元素首先按照普通流的位置出現(xiàn),然后根據(jù)浮動(dòng)的方向盡可能的向左邊或右邊偏移伯复,其效果與印刷排版中的文本環(huán)繞相似慨代。(脫離文檔流,其他dom元素?zé)o視他啸如,在其下方布局侍匙,但是未脫離文本流,其他元素的文本會(huì)認(rèn)為他存在叮雳,環(huán)繞他布局想暗。父元素會(huì)無(wú)視他,因此無(wú)法獲取其高度帘不,這也就是浮動(dòng)元素父元素高度塌陷的原因说莫。) - 絕對(duì)定位 (absolute positioning)
在絕對(duì)定位布局中,元素會(huì)整體脫離普通流寞焙,因此絕對(duì)定位元素不會(huì)對(duì)其兄弟元素造成影響储狭,而元素具體的位置由絕對(duì)定位的坐標(biāo)決定。(完全脫離文檔流捣郊,其他元素?zé)o視他辽狈,在其下方布局)
二、BFC定義
Formatting context(格式化上下文) 是 W3C CSS2.1 規(guī)范中的一個(gè)概念呛牲。它是頁(yè)面中的一塊渲染區(qū)域刮萌,并且有一套渲染規(guī)則,它決定了其子元素將如何定位侈净,以及和其他元素的關(guān)系和相互作用尊勿。
BFC(block formatting content)塊級(jí)格式化上下文僧凤,相對(duì)應(yīng)的有IFC(inline formatting content)內(nèi)聯(lián)格式化上下文畜侦。
那BFC到底是什么呢?
具有 BFC 特性的元素可以看作是隔離了的獨(dú)立容器躯保,容器里面的元素不會(huì)在布局上影響到外面的元素旋膳,并且 BFC 具有普通容器所沒(méi)有的一些特性。通俗一點(diǎn)來(lái)講途事,可以把 BFC 理解為一個(gè)封閉的大箱子验懊,箱子內(nèi)部的元素?zé)o論如何翻江倒海,都不會(huì)影響到外部尸变,外面的元素也無(wú)法影響內(nèi)部义图。
所以,BFC元素不可能發(fā)生margin重疊召烂,因?yàn)閙argin重疊是會(huì)影響到外面的元素碱工;BFC元素也可以用來(lái)清除浮動(dòng)的影響,因?yàn)椴磺宄?dòng)的影響,子元素浮動(dòng)則導(dǎo)致父元素高度塌陷將影響后面的元素布局怕篷。
三历筝、BFC觸發(fā)條件
只要元素滿足下面任一條件即可觸發(fā) BFC 特性:
- body 根元素
- 浮動(dòng)元素:float 除 none 以外的值(left、right廊谓、inherit)
- overflow 除 visible 以外的值 (hidden梳猪、auto、scroll)
- display 為 inline-block蒸痹、table-cells春弥、flex
- 絕對(duì)定位元素:position除relative\static外的值 (absolute(生成絕對(duì)定位的元素,相對(duì)于 static 定位以外的第一個(gè)父元素進(jìn)行定位叠荠。)惕稻、fixed(生成絕對(duì)定位的元素,相對(duì)于瀏覽器窗口進(jìn)行定位蝙叛。)俺祠、inherit(規(guī)定應(yīng)該從父元素繼承 position 屬性的值))
四、BFC 特性及應(yīng)用
- 同一個(gè) BFC 下外邊距會(huì)發(fā)生重疊
<head>
div{
width: 100px;
height: 100px;
background: lightblue;
margin: 100px;
}
</head>
<body>
<div></div>
<div></div>
</body>
從效果上看借帘,因?yàn)閮蓚€(gè) div 元素都處于同一個(gè) BFC 容器下 (這里指 body 元素)蜘渣, 所以第一個(gè) div 的下邊距和第二個(gè) div 的上邊距發(fā)生了重疊,所以兩個(gè)盒子之間距離只有 100px肺然,而不是 200px蔫缸。
首先這不是 CSS 的 bug,我們可以理解為一種規(guī)范际起,如果想要避免外邊距的重疊拾碌,可以將其放在不同的 BFC 容器中。
<div class="container">
<p></p>
</div>
<div class="container">
<p></p>
</div>
.container {
overflow: hidden;
}
p {
width: 100px;
height: 100px;
background: lightblue;
margin: 100px;
}
這時(shí)候街望,兩個(gè)盒子邊距就變成了 200px
- BFC 可以包含浮動(dòng)的元素(清除浮動(dòng)) ——計(jì)算BFC的高度時(shí)校翔,浮動(dòng)元素也參與計(jì)算。
我們都知道灾前,浮動(dòng)的元素會(huì)脫離普通文檔流防症,來(lái)看一個(gè)例子
<div style="border: 1px solid #000;">
<div style="width: 100px;height: 100px;background: #eee;float: left;"></div>
</div>
由于容器內(nèi)元素浮動(dòng),自己就是BFC元素哎甲,然而浮動(dòng)元素有破壞性和包裹性蔫敲,失去了元素本身的流體自適應(yīng)性,脫離了文檔流炭玫,父元素會(huì)無(wú)視他奈嘿,因此無(wú)法獲取其高度,父元素高度塌陷吞加,所以容器只剩下 2px 的邊距高度裙犹。如果使觸發(fā)容器的 BFC酝惧,那么容器將會(huì)包裹著浮動(dòng)元素。
<div style="border: 1px solid #000;overflow: hidden">
<div style="width: 100px;height: 100px;background: #eee;float: left;"></div>
</div>
- BFC 可以阻止元素被浮動(dòng)元素覆蓋
先來(lái)看一個(gè)文字環(huán)繞效果:
<div style="height: 100px;width: 100px;float: left;background: lightblue">我是一個(gè)左浮動(dòng)的元素</div>
<div style="width: 200px; height: 200px;background: #eee">我是一個(gè)沒(méi)有設(shè)置浮動(dòng),
也沒(méi)有觸發(fā) BFC 元素, width: 200px; height:200px; background: #eee;</div>
這時(shí)候其實(shí)第二個(gè)元素有部分被浮動(dòng)元素所覆蓋伯诬,如上圖藍(lán)色部分晚唇,(但是文本信息不會(huì)被浮動(dòng)元素所覆蓋) 如果想避免元素被覆蓋,可觸第二個(gè)元素的 BFC 特性盗似,在第二個(gè)元素中加入 overflow: hidden哩陕,就會(huì)變成:
這個(gè)方法可以用來(lái)實(shí)現(xiàn)兩列自適應(yīng)布局,效果不錯(cuò)赫舒,這時(shí)候左邊的寬度固定悍及,右邊的內(nèi)容自適應(yīng)寬度(去掉上面右邊內(nèi)容的寬度)。實(shí)際中接癌,徹底清除浮動(dòng)不是clear而是overflow,一般使用overflow:hidden心赶,他不會(huì)影響元素原有的流體特征或?qū)挾缺憩F(xiàn)。
總結(jié)
以上例子都體現(xiàn)了:BFC就是頁(yè)面上的一個(gè)隔離的獨(dú)立容器缺猛,容器里面的子元素不會(huì)影響到外面的元素缨叫。反之也如此。
因?yàn)锽FC內(nèi)部的元素和外部的元素絕對(duì)不會(huì)互相影響荔燎,因此耻姥, 當(dāng)BFC外部存在浮動(dòng)時(shí),它不應(yīng)該影響B(tài)FC內(nèi)部Box的布局有咨,BFC會(huì)通過(guò)變窄琐簇,而不與浮動(dòng)有重疊。同樣的座享,當(dāng)BFC內(nèi)部有浮動(dòng)時(shí)婉商,為了不影響外部元素的布局,BFC計(jì)算高度時(shí)會(huì)包括浮動(dòng)的高度渣叛。避免margin重疊也是這樣的一個(gè)道理丈秩。