CSS布局中有一些概念,一旦你理解了它們,就能真正提高你的 CSS 布局能力弛作。本文是關(guān)于塊格式化上下文(BFC)的川蒙。你可能從未聽說過這個術(shù)語,但是如果你曾經(jīng)用CSS做過布局,你可能知道它是什么,理解什么是 BFC,怎么工作以及如何創(chuàng)建 BFC 非常有用亲桥,這些可以幫助你理解CSS中的布局是如何工作的。
在本文中固耘,通過熟悉的示例來解釋什么是 BFC题篷。然后說明 display 的一個新值,只有當(dāng)你理解了什么是 BFC 以及為什么需要它時厅目,它才有意義番枚。
什么是 BFC
在一個Web頁面的CSS渲染中,塊級格式化上下文 (Block Fromatting Context)是按照塊級盒子布局的损敷。W3C對BFC的定義如下:
浮動元素和絕對定位元素葫笼,非塊級盒子的塊級容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不為“visiable”的塊級盒子拗馒,都會為他們的內(nèi)容創(chuàng)建新的BFC(塊級格式上下文)路星。
BFC是一個獨(dú)立的布局環(huán)境,其中的元素布局是不受外界的影響诱桂,并且在一個 BFC 中洋丐,塊盒與行盒(行盒由一行中所有的內(nèi)聯(lián)元素所組成)都會垂直的沿著其父元素的邊框排列呈昔。
塊格式化上下文(BFC)的行為通過一個簡單的float
示例很容易理解。在下面的示例中友绝,我有一個框韩肝,其中包含向左浮動的圖像和一些文本。如果我們有足夠多的文本九榔,它會環(huán)繞浮動的圖像和邊框,然后環(huán)繞整個區(qū)域涡相。
<div class="outer">
<div class="float">I am a floated element.</div>
I am text inside the outer box.
</div>
.outer {
border: 5px dotted rgb(214,129,137);
border-radius: 5px;
width: 450px;
padding: 10px;
margin-bottom: 40px;
}
.float {
padding: 10px;
border: 5px solid rgba(214,129,137,.4);
border-radius: 5px;
background-color: rgba(233,78,119,.4);
color: #fff;
float: left;
width: 200px;
margin: 0 20px 0 0;
}
如果我刪除了一些文本哲泊,那么就沒有足夠的內(nèi)容來包圍圖像,而且由于浮動被從文檔流中脫離催蝗,所以邊框會上升切威,并在圖像下方,直到文本的高度丙号。
這是因?yàn)楫?dāng)我們浮動一個元素時先朦,文本所在的框的寬度保持不變,為給浮動元素騰出空間而縮短的是文本的行框犬缨。這就是為什么背景和邊框會出現(xiàn)在浮動后面的原因喳魏。
我們通常有兩種方法來解決這個布局問題。一種方法是使用 clearfix hack怀薛,它的作用是在文本和圖像下面插入一個元素刺彩,并將其設(shè)置為 clear:both。另一種方法是使用 overflow 屬性枝恋,其值不是缺省值 visible创倔。
.outer {
overflow: auto;
}
overflow 以這種方式工作的原因是,使用 visible 的初值以外的任何值都會創(chuàng)建一個塊格式化上下文焚碌,而 BFC 的一個特性是它包含浮動畦攘。
BFC 是布局中的一個迷你布局
你可以將 BFC 看作是頁面內(nèi)的一個迷你布局。一旦一個元素創(chuàng)建了一個 BFC十电,它就包含了所有的內(nèi)容知押。正如我們所看到的,這包括浮動的元素鹃骂,它們不再從盒子底部伸出來朗徊。BFC 還會導(dǎo)致一些其他有用的行為。
BFC 可以防止 margin 折疊
了解邊距合并是另一個被低估的 CSS 技能偎漫。在下一個示例中爷恳,假設(shè)有一個背景顏色為灰色的 div
。這個 div
包含兩個標(biāo)簽 p
象踊。外部 div
元素的 margin-bottom
為 40 像素温亲,標(biāo)簽 p
的頂部和底部 margin
都是 20 像素棚壁。
<div class="outer">
<p>I am paragraph one and I have a margin top and bottom of 20px;</p>
<p>I am paragraph one and I have a margin top and bottom of 20px;</p>
</div>
.outer {
background-color: #ccc;
margin: 0 0 40px 0;
}
p {
padding: 0;
margin: 20px 0 20px 0;
background-color: rgb(233,78,119);
color: #fff;
}
因?yàn)?p
元素的 margin
和外部 div
上的 margin
之間沒有任何東西,所以兩個會折疊栈虚,因此 p
最終與 div
的頂部和底部齊平袖外。 我們在 p
的上方和下方看不到任何灰色。
在CSS當(dāng)中魂务,相鄰的兩個盒子(可能是兄弟關(guān)系也可能是祖先關(guān)系)的外邊距可以結(jié)合成一個單獨(dú)的外邊距曼验。這種合并外邊距的方式被稱為折疊,并且因而所結(jié)合成的外邊距稱為折疊外邊距粘姜。折疊的結(jié)果按照如下規(guī)則計(jì)算:
- 兩個相鄰的外邊距都是正數(shù)時鬓照,折疊結(jié)果是它們兩者之間較大的值。
- 兩個相鄰的外邊距都是負(fù)數(shù)時孤紧,折疊結(jié)果是兩者絕對值的較大值豺裆。
- 兩個外邊距一正一負(fù)時,折疊結(jié)果是兩者的相加的和号显。
產(chǎn)生折疊的必備條件:margin必須是鄰接的!
如果我們把盒子設(shè)為 BFC臭猜,它現(xiàn)在包含了標(biāo)簽 p 和它們的邊距,這樣它們就不會折疊押蚤,我們可以看到邊距后面容器的灰色背景蔑歌。
.outer {
background-color: #ccc;
margin: 0 0 40px 0;
overflow: auto;
}
再一次,BFC 的工作是把東西裝在盒子里揽碘,防止它們從盒子里跑出來丐膝。
BFC 可以阻止元素被浮動元素覆蓋
你將熟悉 BFC 的這種行為,因?yàn)槭褂酶拥娜魏瘟蓄愋筒季侄际沁@樣工作的钾菊。如果一個項(xiàng)目創(chuàng)建了一個 BFC帅矗,那么該項(xiàng)目將不會包裹任何浮動元素。在下面的例子中煞烫,有如下 html 結(jié)構(gòu):
<div class="outer">
<div class="float">I am a floated element.</div>
<div class="text">I am text</div>
</div>
帶有 float 類的項(xiàng)被向左浮動浑此,因此 div 中的文本在它環(huán)繞 float 之后。
我可以通過將包裹文本的 div 設(shè)置為 BFC 來防止這種包裹行為滞详。
.text {
overflow: auto;
}
這實(shí)際上是我們創(chuàng)建具有多個列的浮動布局的方法凛俱。浮動項(xiàng)還為該項(xiàng)創(chuàng)建了一個 BFC,因此料饥,如果右邊的列比左邊的列高蒲犬,那么我們的列就不會相互環(huán)繞。
在多列布局中使用 BFC
如果我們創(chuàng)建一個占滿整個容器寬度的多列布局岸啡,在某些瀏覽器中最后一列有時候會掉到下一行原叮。這可能是因?yàn)闉g覽器四舍五入了列寬從而所有列的總寬度會超出容器。但如果我們在多列布局中的最后一列里創(chuàng)建一個新的BFC,它將總是占據(jù)其他列先占位完畢后剩下的空間奋隶。
例如:
<div class="container">
<div class="column">column 1</div>
<div class="column">column 2</div>
<div class="column">column 3</div>
</div>
對應(yīng)的CSS:
.column {
width: 31.33%;
background-color: green;
float: left;
margin: 0 1%;
}
.column:last-child {
float: none;
}
未創(chuàng)建 BFC 之前:
添加以下樣式創(chuàng)建一個 BFC:
.column:last-child {
float: none;
overflow: hidden;
}
現(xiàn)在盡管盒子的寬度稍有改變擂送,但布局不會打破。當(dāng)然唯欣,對多列布局來說這不一定是個好辦法嘹吨,但能避免最后一列下掉。這個問題上彈性盒或許是個更好的解決方案境氢,但這個辦法可以用來說明元素在這些環(huán)境下的行為蟀拷。
還有什么能創(chuàng)建 BFC?
除了使用 overflow 創(chuàng)建 BFC 外,其他一些 CSS 屬性還創(chuàng)建 BFC萍聊。正如我們所看到的问芬,浮動元素創(chuàng)建了 BFC。你的浮動項(xiàng)將包含它里面的任何東西脐区。
使用以下方式都能創(chuàng)建 BFC
- float 的值不是 none。
- position 的值不是 static 或者 relative她按。
- display 的值是 inline-block牛隅、table-cell、flex酌泰、table-caption 或者inline-flex媒佣。
- overflow 的值不是 visible。
創(chuàng)建 BFC 的新方式
使用overflow或其他的方法創(chuàng)建BFC時會有兩個問題陵刹。首先默伍,這些方法本身是有自身的設(shè)計(jì)目的,所以在使用它們創(chuàng)建BFC時可能會產(chǎn)生副作用衰琐。例如也糊,使用overflow創(chuàng)建BFC后在某些情況下可能會看到出現(xiàn)一個滾動條或者元素內(nèi)容被裁切。
這是由于overflow屬性的設(shè)計(jì)是用來讓你告訴瀏覽器如何定義元素的溢出狀態(tài)的羡宙。瀏覽器執(zhí)行了它最基本的定義狸剃。
即使在沒有任何不想要的副作用的情況下,使用 overflow 也可能會讓其他開發(fā)人員感到困惑狗热。為什么 overflow 設(shè)置為 auto 或 scroll?最初的開發(fā)者的意圖是什么?他們想要這個組件上的滾動條嗎?
最安全的做法應(yīng)該是創(chuàng)建一個 BFC 時并不會帶來任何副作用钞馁,它內(nèi)部的元素都安全的呆在這個迷你布局中,這種方法不會引起任何意想不到的問題匿刮,也可以理解開發(fā)者的意圖僧凰。CSS 工作組也十分認(rèn)同這種想法,所以他們定制了一個新的屬性值:**display:flow-root**
熟丸。
flow-root 瀏覽器支持情況
你可以使用 display:flow-root 安全的創(chuàng)建 BFC训措,來解決上文中提到的各種問題:包裹浮動元素、阻止外邊距疊加和阻止圍繞浮動元素。
瀏覽器對該屬性的支持目前還是有限的隙弛,如果你覺得這個屬性值很方便架馋,請投票去讓Edge也支持它。不過無論如何全闷,你現(xiàn)在應(yīng)該已經(jīng)理解了什么是 BFC叉寂,以及如何使用 overflow 或其他方法來包裹浮動,以及知道了 BFC 可以阻止元素去環(huán)繞浮動元素总珠,如果你想使用彈性或網(wǎng)格布局可以在一些不支持他們的瀏覽器中使用 BFC 的這些特性做降級處理屏鳍。
理解瀏覽器如何布置網(wǎng)頁是非常基礎(chǔ)的局服。 雖然有時看起來無關(guān)緊要钓瞭,但是這些小知識可以加快創(chuàng)建和調(diào)試 CSS 布局所需的時間。
轉(zhuǎn)自前端小智
感興趣的小伙伴可以在公號【grain先森】后臺回復(fù)【190315】獲取【Css 參考規(guī)范】淫奔,可以轉(zhuǎn)發(fā)朋友圈和你的朋友分享哦山涡。