理解 Css 布局和 BFC

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;
}
float示例

如果我刪除了一些文本哲泊,那么就沒有足夠的內(nèi)容來包圍圖像,而且由于浮動被從文檔流中脫離催蝗,所以邊框會上升切威,并在圖像下方,直到文本的高度丙号。

刪除一些文本

這是因?yàn)楫?dāng)我們浮動一個元素時先朦,文本所在的框的寬度保持不變,為給浮動元素騰出空間而縮短的是文本的行框犬缨。這就是為什么背景和邊框會出現(xiàn)在浮動后面的原因喳魏。

我們通常有兩種方法來解決這個布局問題。一種方法是使用 clearfix hack怀薛,它的作用是在文本和圖像下面插入一個元素刺彩,并將其設(shè)置為 clear:both。另一種方法是使用 overflow 屬性枝恋,其值不是缺省值 visible创倔。

.outer {
  overflow: auto;
}
overflow

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 的上方和下方看不到任何灰色。

防止 margin 折疊

在CSS當(dāng)中魂务,相鄰的兩個盒子(可能是兄弟關(guān)系也可能是祖先關(guān)系)的外邊距可以結(jié)合成一個單獨(dú)的外邊距曼验。這種合并外邊距的方式被稱為折疊,并且因而所結(jié)合成的外邊距稱為折疊外邊距粘姜。折疊的結(jié)果按照如下規(guī)則計(jì)算:

  1. 兩個相鄰的外邊距都是正數(shù)時鬓照,折疊結(jié)果是它們兩者之間較大的值。
  2. 兩個相鄰的外邊距都是負(fù)數(shù)時孤紧,折疊結(jié)果是兩者絕對值的較大值豺裆。
  3. 兩個外邊距一正一負(fù)時,折疊結(jié)果是兩者的相加的和号显。

產(chǎn)生折疊的必備條件:margin必須是鄰接的!
如果我們把盒子設(shè)為 BFC臭猜,它現(xiàn)在包含了標(biāo)簽 p 和它們的邊距,這樣它們就不會折疊押蚤,我們可以看到邊距后面容器的灰色背景蔑歌。

.outer {
  background-color: #ccc;
  margin: 0 0 40px 0;
  overflow: auto;
}
產(chǎn)生折疊的必備條件

再一次,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 之后。

帶有 float 類的項(xiàng)

我可以通過將包裹文本的 div 設(shè)置為 BFC 來防止這種包裹行為滞详。

.text {
  overflow: auto;
}
將包裹文本的div設(shè)置為BFC

這實(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 之前

添加以下樣式創(chuàng)建一個 BFC:

.column:last-child {
  float: none;
  overflow: hidden; 
}
創(chuàng)建一個 BFC

現(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训措,來解決上文中提到的各種問題:包裹浮動元素、阻止外邊距疊加和阻止圍繞浮動元素。

flow-root 瀏覽器支持情況

瀏覽器對該屬性的支持目前還是有限的隙弛,如果你覺得這個屬性值很方便架馋,請投票去讓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ā)朋友圈和你的朋友分享哦山涡。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市唆迁,隨后出現(xiàn)的幾起案子鸭丛,更是在濱河造成了極大的恐慌,老刑警劉巖唐责,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鳞溉,死亡現(xiàn)場離奇詭異,居然都是意外死亡鼠哥,警方通過查閱死者的電腦和手機(jī)熟菲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來朴恳,“玉大人抄罕,你說我怎么就攤上這事∮谟保” “怎么了贞绵?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長恍飘。 經(jīng)常有香客問我榨崩,道長,這世上最難降的妖魔是什么章母? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任母蛛,我火速辦了婚禮,結(jié)果婚禮上乳怎,老公的妹妹穿的比我還像新娘彩郊。我一直安慰自己前弯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布秫逝。 她就那樣靜靜地躺著恕出,像睡著了一般。 火紅的嫁衣襯著肌膚如雪违帆。 梳的紋絲不亂的頭發(fā)上浙巫,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機(jī)與錄音刷后,去河邊找鬼的畴。 笑死,一個胖子當(dāng)著我的面吹牛尝胆,可吹牛的內(nèi)容都是我干的丧裁。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼含衔,長吁一口氣:“原來是場噩夢啊……” “哼煎娇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起贪染,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤缓呛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后抑进,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體强经,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡睡陪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年寺渗,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兰迫。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡信殊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出汁果,到底是詐尸還是另有隱情涡拘,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布据德,位于F島的核電站鳄乏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏棘利。R本人自食惡果不足惜橱野,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望善玫。 院中可真熱鬧水援,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至奕扣,卻和暖如春薪鹦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背成畦。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工距芬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人循帐。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓框仔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拄养。 傳聞我的和親對象是個殘疾皇子离斩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,728評論 1 92
  • 一瘪匿,浮動元素有什么特征跛梗?對父容器、其他浮動元素棋弥、普通元素核偿、文字分別有什么影響? 浮動模型是一種可視化格式模型,浮動...
    DeeJay_Y閱讀 858評論 0 4
  • CSS布局中有一些概念是你一旦理解它那么就會極大的提升你的CSS技能的顽染。這篇文章是關(guān)于塊級格式化上下文的BFC漾岳。也...
    強(qiáng)哥科技興閱讀 430評論 0 0
  • 流云西去 拂過一灣碧水 夕陽披錦 染紅半邊藍(lán)天 憑欄望遠(yuǎn) 沉醉不忍歸去
    在雨縫中行走閱讀 215評論 4 4
  • 《戰(zhàn)狼2》最近很火尼荆,持續(xù)刷屏,票房蹭蹭的往上漲唧垦,據(jù)說已經(jīng)突破50億了捅儒,熱度依然不減。按照目前院線火爆情況估算振亮,票房...
    冷冷123456閱讀 660評論 4 4