Original Author: Ritesh Kumarcss
Original Article: http://www.sitepoint.com/understanding-block-formatting-contexts-in-css/segmentfault
Translator: HaoyCn瀏覽器
Date: 9th of Aug, 2015ide
塊級格式化上下文(Block Formatting Context)是網頁CSS視覺渲染的一部分,並用於決定塊盒子的佈局。在定位體系(Positioning Scheme)中它屬於常規流(Normal Flow)。根據W3C所言:wordpress
浮動、絕對定位元素(
position
爲absolute
或fixed
)、行內塊元素display:inline-block
、表格單元格display:table-cell
、表格標題display:table-caption
以及overflow
屬性值不爲visible
的元素(除了該值被傳播到視點viewport
的狀況)將建立一個新的塊級格式化上下文。佈局
上面的引言差很少總結了一個BFC是如何造成的。但讓我們用另一種更通俗易懂的方式來重定義它。一個BFC就是一個HTML盒子,它至少知足如下條件之一:flex
float
的值不爲 none
spa
position
的值不爲 static
或 relative
翻譯
display
的值爲 table-cell
、table-caption
、inline-block
、flex
或 inline-flex
code
overflow
的值不爲 visiable
一個BFC能夠顯式觸發。若是咱們想建立之,咱們只需給它添加上面提到的任何一個CSS樣式。
好比,看下面的HTML:
<div class="container"> Some Content here </div>
一個新的BFC能夠經過給容器添加任意一個必要的CSS樣式來建立,好比overflow: scroll
,overflow: hidden
,display: flex
,float: left
,或 display: table
。儘管上述條件均可以建立BFC,但也會產生一些其餘效果,如:
display: table
可能引起響應性問題
overflow: scroll
可能產生多餘的滾動條
float: left
將把元素移至左側,並被其餘元素環繞
overflow: hidden
將裁切溢出元素
因此不管什麼時候,當要建立一個BFC時,咱們要基於需求選擇最恰當的樣式。爲了保持一致性,我在本文的全部例子中均使用 overflow: hidden
。
.container { overflow: hidden; }
你能夠自由選擇使用除 overflow: hidden
以外的其餘樣式。
W3C規範道:
在BFC上下文中,每一個盒子的左外側緊貼包含塊的左側(從右到左的格式裏,則爲盒子右外側緊貼包含塊右側),甚至有浮動也是如此(儘管盒子裏的行盒子
Line Box
可能因爲浮動而變窄),除非盒子建立了一個新的BFC(在這種狀況下盒子自己可能因爲浮動而變窄)。
簡單來講,如上圖所示,因此屬於BFC的盒子都左對齊(在從左到右的格式下)而且它們的左外側緊貼包含塊的左側。在最後一個盒子中咱們能夠看到儘管左側存在一個浮動元素(棕色),另一個元素(綠色)仍然緊貼包含塊的左側。該狀況的產生原理將在下文關於文字環繞的部分中討論。
在常規流中,盒子從包含塊的頂部開始一個個地垂直襬放。兩個同胞盒子間的垂直舉例由兩個盒子各自的外邊距所決定,但不是兩者外邊距之和。
爲便於理解,咱們看個例子。
在上圖中,一個紅盒子(div
)包含着兩個同胞綠元素(p
),一個BFC已經建立了出來。
<div class="container"> <p>Sibling 1</p> <p>Sibling 2</p> </div>
相應的CSS是:
.container { background-color: red; overflow: hidden; /* creates a block formatting context */ } p { background-color: lightgreen; margin: 10px 0; }
理論上兩個同胞元素間的外邊距應當是兩者外邊距之和(20px)但實際上倒是10px。這就是衆所周知的外邊距摺疊(Collapsing Margins)。若是同胞元素外邊距不一樣,將應用最大的那個。
在討論了上面BFC摺疊外邊距的狀況後,如今說避免摺疊可能有點讓人摸不着頭腦。但咱們必須牢記於心的一件事是,相鄰塊級盒子(同胞)之間的垂直外邊距只有在它們處於同一個BFC時纔會發生摺疊。若是它們分屬於不一樣的BFC,就不會摺疊了。因此,經過建立新的BFC咱們能夠避免外邊距摺疊。
讓咱們在早前的例子中添加第三個同胞元素,如今HTML是:
<div class="container"> <p>Sibling 1</p> <p>Sibling 2</p> <p>Sibling 3</p> </div>
CSS是:
.container { background-color: red; overflow: hidden; /* creates a block formatting context */ } p { background-color: lightgreen; margin: 10px 0; }
結果和上面同樣,便是說,摺疊仍是會發生而且三個同胞間分隔的垂直距離是10px。這是由於三個 p
標籤都從屬於同一個BFC。
如今咱們修改第三個同胞元素,使之成爲一個新的BFC的一部分。如今的HTML變成了:
<div class="container"> <p>Sibling 1</p> <p>Sibling 2</p> <div class="newBFC"> <p>Sibling 3</p> </div> </div>
CSS:
.container { background-color: red; overflow: hidden; /* creates a block formatting context */ } p { margin: 10px 0; background-color: lightgreen; } .newBFC { overflow: hidden; /* creates new block formatting context */ }
如今輸出的結果就有所不一樣了:
由於第二個和第三個同胞元素如今分屬於不一樣的BFC,它們之間就不會發生外邊距摺疊了。
BFC能夠包含浮動。咱們常常遇到容器中含有浮動元素的狀況。這種狀況下容器元素沒有高度而且其浮動子元素脫離了網頁的常規流。咱們一般用清除浮動解決這個問題,最廣泛的作法就是使用僞元素。但咱們也能夠經過建立一個BFC來解決問題。
看個例子:
<div class="container"> <div>Sibling</div> <div>Sibling</div> </div>
CSS:
.container { background-color: green; } .container div { float: left; background-color: lightgreen; margin: 10px; }
在上面這個例子中,容器沒有任何高度,而且它包不住浮動子元素。爲解決此問題,咱們經過添加 overflow: hidden
來在容器中建立一個新的BFC。修改後的CSS成了:
.container { overflow: hidden; /* creates block formatting context */ background-color: green; } .container div { float: left; background-color: lightgreen; margin: 10px; }
如今容器能夠包住浮動子元素,而且其高度會擴展至包住其子元素,在這個新的BFC中浮動元素又迴歸到頁面的常規流之中了。
有時候浮動DIV旁邊的文本會環繞它(以下圖1所示)而這種狀況有時候並不如咱們所願,咱們想要下圖2的效果。要解決這個問題,咱們能夠用外邊距,但也能夠用BFC。
首先讓咱們弄明白爲什麼文字會環繞。要理解這個咱們必須明白,當存在元素浮動的時候,盒模型如何工做。這就是我早先討論BFC中對齊時候的遺留問題。咱們經過下圖來看圖1到底發生了什麼。
假設HTML是:
<div class="container"> <div class="floated"> Floated div </div> <p> Quae hic ut ab perferendis sit quod architecto, dolor debitis quam rem provident aspernatur tempora expedita. </p> </div>
上圖整個黑色區域表示 p
元素,如咱們所見,p
元素沒有移位但它疊在了浮動元素之下,而p
元素的行盒子(即文本行)卻移位了,行盒子水平變窄來給浮動元素騰出了空間。
隨着文本的增長,最後文本將環繞在浮動元素之下,由於那時候行盒子再也不須要移位,也就成了圖1的樣子。這就是爲何即使有浮動元素,段落仍緊貼包含塊的左側,而行盒子會變窄來給浮動元素騰位子。
若是咱們能位移整個 p
元素,這個環繞問題也就迎刃而解了。
在說解決方案以前,咱們再回顧下W3C規範:
在BFC上下文中,每一個盒子的左外側緊貼包含塊的左側(從右到左的格式裏,則爲盒子右外側緊貼包含塊右側),甚至有浮動也是如此(儘管盒子裏的行盒子
Line Box
可能因爲浮動而變窄),除非盒子建立了一個新的BFC(在這種狀況下盒子自己可能因爲浮動而變窄)。
據此,若是 p
元素建立一個新的BFC那它就不會再緊貼包含塊的左側了。給 p
元素添加 overflow: hidden
就能垂手可得地辦到。這解決了文本環繞浮動對象的問題。
若是咱們建立一個佔滿整個容器寬度的多列布局,在某些瀏覽器中最後一列有時候會掉到下一行。這多是由於瀏覽器四捨五入了列寬從而全部列的總寬度會超出容器。但若是咱們在多列布局中的最後一列裏建立一個新的BFC,它將老是佔據其餘列先佔位完畢後剩下的空間。
咱們來舉個三列布局的例子:
這是HTML:
<div class="container"> <div class="column">column 1</div> <div class="column">column 2</div> <div class="column">column 3</div> </div>
CSS:
.column { width: 31.33%; background-color: green; float: left; margin: 0 1%; } /* Establishing a new block formatting context in the last column */ .column:last-child { float: none; overflow: hidden; }
如今儘管盒子的寬度稍有改變,但佈局不會打破。固然,對多列布局來講這不必定是個好辦法,但能避免最後一列下掉。這個問題上彈性盒或許是個更好的解決方案,但這個辦法能夠用來講明元素在這些環境下的行爲。
我但願本文已經向你展現了BFC的特性以及BFC是如何影響頁面上的元素的視圖定位的。展現其用法的例子應該有讓BFC顯得更透徹一些。
若是你有任何想要補充的,請在評論裏留言。若是你想更深刻了解的話,必定得去回顧W3C對這個話題的詳述。
本文中說起的浮動與行盒子變窄問題深刻探討,能夠參看博文:http://www.zhangxinxu.com/wordpress/?p=583
W3C標準中「除了該值被傳播到視點 viewport
的狀況」,能夠參看問題:http://segmentfault.com/q/1010000002645174
轉載本文亦請同時註明原出處(見本文頂部)。如您承認本文翻譯,歡迎推薦或收藏,謝謝!