BFC是什么?
入門FE了那么久,BFC這個(gè)名詞倒是第一次知道,特地前去了解了一下,幡然醒悟,這不就是平常我們寫block和inline的標(biāo)準(zhǔn)文檔流嗎?(恕我不專業(yè)的描述方式),估計(jì)是自己知識(shí)面太窄了,不然咋會(huì)在學(xué)習(xí)CSS的時(shí)候錯(cuò)過(guò)捏,呵呵噠。
Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with ‘overflow’ other than ‘visible’ (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.
————W3C
中文直譯為塊級(jí)格式上下文(或塊級(jí)上下文)。其實(shí)就是我們平常的塊級(jí)元素自頂向下排列,同級(jí)之間的containing block頂部一個(gè)接一個(gè)垂直排列,水平方向上撐滿寬度。
因?yàn)閮蓚€(gè)相鄰的BFC之間距離由margin決定,在同一個(gè)BFC內(nèi)部,兩個(gè)垂直方向相鄰的塊級(jí)元素margin值會(huì)"共用",導(dǎo)致塌陷。也是經(jīng)典的外邊距塌陷問(wèn)題。
以下方法可以創(chuàng)建一個(gè)新的塊級(jí)執(zhí)行上下文(BFC):
- 浮動(dòng)元素
- 絕對(duì)定位元素
- 塊級(jí)元素以及塊級(jí)容器(比如inline-block、table-cell、table-capation)
- overflow值不為visible的塊級(jí)盒子
當(dāng)然,root元素會(huì)自動(dòng)生成一個(gè)BFC,這個(gè)應(yīng)該很好理解,畢竟需要一個(gè)根BFC來(lái)布局
執(zhí)行規(guī)則:
- 在一個(gè)塊級(jí)排版上下文中,盒子是從包含塊頂部開(kāi)始,垂直的一個(gè)接一個(gè)的排列的。每個(gè)盒子的左外邊是觸碰到包含塊的左邊的(對(duì)于從右向左的排版,則相反)
- 相鄰兩個(gè)盒子之間的垂直的間距是被margin屬性所決定的,在一個(gè)塊級(jí)排版上下文中相鄰的兩個(gè)塊級(jí)盒之間的垂直margin是折疊的。
注意:這里著重了解一下,什么是同一個(gè)BFC、根BFC,有何區(qū)別
我們來(lái)實(shí)現(xiàn)它。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
div {
width: 200px;
height: 100px;
}
.a {
background-color: red;
}
.b {
background-color: orange;
}
.c {
background-color: deepskyblue;
}
.d {
background-color: black;
margin: 20px;
}
.e {
background-color: green;
margin: 20px;
}
</style>
</head>
<body>
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<div class="d"></div>
<div class="e"></div>
</body>
</html>
示例1
這是最普通的塊級(jí)排版上下文,現(xiàn)在問(wèn)題來(lái)了,這里有新的BFC嗎?對(duì)比那4個(gè)方法......沒(méi)有對(duì)嗎,所以,這里的所有class都是同一種BFC或者說(shuō)同一個(gè)BFC(這個(gè)準(zhǔn)確些吧),他們遵守執(zhí)行規(guī)則第一項(xiàng),依次向下排列......
在.d
和.e
我加了margin值,但是我們發(fā)現(xiàn),兩者中間的垂直margin并沒(méi)有生效,否則應(yīng)該是40px才對(duì)。
這就是執(zhí)行規(guī)則2生效了。
- 垂直margin合并
在CSS當(dāng)中,相鄰的兩個(gè)盒子的外邊距可以結(jié)合成一個(gè)單獨(dú)的外邊距。這種合并外邊距的方式被稱為折疊,并且因而所結(jié)合成的外邊距稱為折疊外邊距。
折疊的結(jié)果:
- 兩個(gè)相鄰的外邊距都是正數(shù)時(shí),折疊結(jié)果是它們兩者之間較大的值。
- 兩個(gè)相鄰的外邊距都是負(fù)數(shù)時(shí),折疊結(jié)果是兩者絕對(duì)值的較大值。
- 兩個(gè)外邊距一正一負(fù)時(shí),折疊結(jié)果是兩者的相加的和。
- 這個(gè)同樣可以利用BFC解決。關(guān)于原理在前文已經(jīng)講過(guò)了。
————引用自簡(jiǎn)書蘇星河
所以我們用BFC解決margin合并,如何解決呢?就是建立一個(gè)新的BFC,使得他倆沒(méi)有關(guān)系。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 200px;
height: 100px;
}
.d {
background-color: black;
margin: 20px;
display: inline-block;
}
.e {
background-color: green;
margin: 20px;
}
</style>
</head>
<body>
<div class="d"></div>
<div class="e"></div>
</body>
</html>
示例二
在其中一個(gè)div的display改為inline-block,創(chuàng)建一個(gè)新的BFC,使得兩者BFC所屬不同。
浮動(dòng)父容器塌陷問(wèn)題
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.wrap {
border: solid 1px red;
width: 250px;
}
.a,.b {
width: 100px;
height: 50px;
background-color: orange;
float: left;
}
.b {
background-color: blue;
}
</style>
</head>
<body>
<div class="wrap">
<div class="a"></div>
<div class="b"></div>
</div>
</body>
</html>
我是這么理解的,內(nèi)部的兩個(gè)div由于float,所以不在屬于root BFC,則外容器內(nèi)部不再有同樣的BFC,判定為無(wú)內(nèi)容(這里其實(shí)有歧義),所以紅色框沒(méi)有撐開(kāi)。
從BFC的角度看解決方法
我們調(diào)整一下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.wrap {
border: solid 5px red;
width: 250px;
overflow: hidden;
}
.a,.b {
width: 100px;
height: 50px;
background-color: orange;
float: left;
}
.b {
background-color: blue;
}
</style>
</head>
<body>
<div class="wrap">
<div class="a"></div>
<div class="b"></div>
</div>
</body>
</html>
通過(guò)對(duì)父容器添加overflow:hidden
,改變它的BFC,這樣處于同樣的BFC下的容器就會(huì)將子div內(nèi)容算入,撐開(kāi)父容器。
BFC與文字環(huán)繞
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.ct {
border: solid 1px black;
}
.aside {
width: 50px;
height: 50px;
background-color: red;
float: left;
}
.content {
background-color: orange;
}
</style>
</head>
<body>
<div class="ct">
<div class="aside"></div>
<div class="content">公園里還有一處燒烤區(qū),一邊看著遠(yuǎn)處聳立的高樓,一邊吃著燒烤,也許臉書的員工就是喜歡這種自然田園的風(fēng)光。
說(shuō)實(shí)話,在硅谷這個(gè)寸土寸金的地方,臉書總部里能有這么大一塊地作為公園我覺(jué)得是挺奢侈的,但是真的要比較起來(lái),國(guó)內(nèi)很多公園都比這個(gè)要做地精致和好看。連作者本人也這么覺(jué)得:</div>
</div>
</body>
</html>
如何做到和右圖一樣呢?
先看看造成這個(gè)現(xiàn)象的原因
橙色區(qū)域?yàn)?code>line-boxs,從表面看,文字盒子被浮動(dòng)紅盒子擠壓到了左邊,實(shí)際上,由于紅盒子浮動(dòng),是新的BFC,文字盒子實(shí)際上是從父容器左邊開(kāi)始的,文字盒子實(shí)際上處于浮動(dòng)元素的下方。文字盒子進(jìn)行了移位,水平收縮為浮動(dòng)元素提供了空間。
隨著文字增加,文字盒子最終將會(huì)環(huán)繞在浮動(dòng)元素下方,也就是現(xiàn)在這樣。
我們?nèi)绻芤苿?dòng)文字盒子,也就是文字的容器,就可以使它不環(huán)繞了。此處想一想W3C的概念:
In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itselfmay become narrowerdue to the floats).
在BFC中,每個(gè)盒子的左外邊框緊挨著左邊框的包含塊(從右到左的格式化時(shí),則為右邊框緊挨)。即使在浮動(dòng)里也是這樣的(盡管一個(gè)盒子的邊框會(huì)因?yàn)楦?dòng)而萎縮),除非這個(gè)盒子的內(nèi)部創(chuàng)建了一個(gè)新的BFC(這種情況下,由于浮動(dòng),盒子本身將會(huì)變得更窄),
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.ct {
border: solid 1px black;
}
.aside {
width: 50px;
height: 50px;
background-color: red;
float: left;
}
.content {
background-color: orange;
overflow: hidden;
}
</style>
</head>
<body>
<div class="ct">
<div class="aside"></div>
<div class="content">公園里還有一處燒烤區(qū),一邊看著遠(yuǎn)處聳立的高樓,一邊吃著燒烤,也許臉書的員工就是喜歡這種自然田園的風(fēng)光。
說(shuō)實(shí)話,在硅谷這個(gè)寸土寸金的地方,臉書總部里能有這么大一塊地作為公園我覺(jué)得是挺奢侈的,但是真的要比較起來(lái),國(guó)內(nèi)很多公園都比這個(gè)要做地精致和好看。連作者本人也這么覺(jué)得:</div>
</div>
</body>
</html>
文字盒子添加overflow:hidden,使得處于新的BFC中,就不會(huì)根據(jù)上面的W3C概念規(guī)則來(lái)繪制了。
MDN——外邊距合并
蘇星河:【CSS】深入理解BFC原理及應(yīng)用
CSS深入理解流體特性和BFC特性下多欄自適應(yīng)布局
CSS布局基礎(chǔ):BFC
理解CSS中BFC
BFC神器背后的原理