BFC

什麼是BFC

在一個web頁面的CSS渲染中,塊級格式化上下文(Block Formatting Context)是按照塊級盒子佈局的。W3C對BFC的定義以下:php

浮動元素和絕對定位元素,非塊級盒子的塊級容器(例如inline-blocks,table-cells和table-captions),以及overflow值不爲「visible」的塊級盒子,都會爲他們的內容建立新的BFC(塊級格式化上下文)。html

爲了便於理解,咱們換一種方式來從新定義BFC。一個HTTP元素要建立BFC,則要知足下列的任意一個或多個條件便可:web

  1. float值不是none
  2. position的值不是static或者relative
  3. display的值是inline-block、table-cell、flex、table-caption或者inline-flex
  4. overflow的值不是visible

BFC是一個獨立的佈局環境,其中的元素佈局是不受外界的影響,而且在一個BFC中,塊盒與行盒(行盒由一行中全部的內聯元素所組成)都會垂直地沿着其父元素的邊框排列。chrome

 

怎麼建立BFC

要顯示地建立一個BFC是很是簡單的,只要知足上述4個CSS條件之一就行。例如:瀏覽器

<div class='container'>
   你的內容。。。
</div>

在類container中添加相似overflow:scroll, overflow:hidden, display:flex, float:left, 或者display:table的規則來顯示建立BFC。雖然添加上述的任意一條都能建立BFC,但會有一些反作用:app

  1. display:table可能會引起響應性問題
  2. overflow:scroll可能產生多餘的滾動條
  3. float:left將把元素移至左側,並被其餘元素環繞
  4. overflow:hidden 將裁切溢出元素

於是不管何時須要建立BFC,都要基於自身的須要來考慮。對於本文,將採用overflow: hidden方式:ide

.container {
    overflow: hidden
}

 

BFC中盒子怎麼對齊

如前文所說,在一個BFC中,塊盒與行盒(行盒由一行中全部的內聯元素所組成)都會垂直的沿着其父元素的邊框排列。W3C給出得規範是:佈局

在BFC中,每個盒子的左外邊緣(margin-left)會觸碰到容器的左邊緣(border-left)(對於從右到左的格式來講,則觸碰到右邊緣)。浮動也是如此(儘管盒子裏的行盒子 Line Box 可能因爲浮動而變窄),除非盒子建立了一個新的BFC(在這種狀況下盒子自己可能因爲浮動而變窄)。flex

外邊距重疊

常規流佈局時,盒子都是垂直排列,二者之間的間距由各自的外邊距所決定,可是不是兩者外邊距之和。ui

<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;
}

渲染結果如圖:

在上圖中,一個紅盒子(div)包含着兩個兄弟元素(p),一個BFC已經建立了出來。

理論上,兩個p元素之間的外邊距應當是兩者外邊距之和(20px)但實際上倒是10px,這是外邊距摺疊(Collapsing Margins)的結果。

在CSS當中,相鄰的兩個盒子(多是兄弟關係也多是祖先關係)的外邊距能夠結合成一個單獨的外邊距。這種合併外邊距的方式被稱爲摺疊,而且於是所結合成的外邊距稱爲摺疊外邊距。摺疊的結果按照以下規則計算:

一、兩個相鄰的外邊距都是正數時,摺疊結果是它們二者之間較大的值。
二、兩個相鄰的外邊距都是負數時,摺疊結果是二者絕對值的較大值。
三、兩個外邊距一正一負時,摺疊結果是二者的相加的和。

產生摺疊的必備條件:margin必須是鄰接的!

水平方向的外邊距是不會發生重疊的。

 

利用BFC避免外邊距摺疊

BFC可能形成外邊距摺疊,也能夠利用它來避免這種狀況。BFC產生外邊距摺疊要知足一個條件:兩個相鄰元素要處於同一個BFC中。因此,若兩個相鄰元素在不一樣的BFC中,就能避免外邊距摺疊。

改進前面的例子:

<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;
}

結果和上面同樣,因爲外邊距摺疊,三個相鄰P元素之間的垂直距離是10px,這是由於三個 p 標籤都從屬於同一個BFC。

修改第三個P元素,使之建立一個新的BFC:

<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 */
}

 

 由於第二個和第三個P元素如今分屬於不一樣的BFC,它們之間就不會發生外邊距摺疊了。

 

BFC包含浮動

浮動元素是會脫離文檔流的(絕對定位元素會脫離文檔流)。若是一個沒有高度或者height是auto的容器的子元素是浮動元素,則該容器的高度是不會被撐開的。咱們一般會利用僞元素(:after或者:before)來解決這個問題。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; }

在上面這個例子中,容器沒有任何高度,而且它包不住浮動子元素,容器的高度並不會被撐開。爲解決這個問題,能夠在容器中建立一個BFC:

.container {
    overflow: hidden; /* creates block formatting context */
    background-color: green;
}
.container div {
    float: left;
    background-color: lightgreen;
    margin: 10px;
}

如今容器能夠包住浮動子元素,而且其高度會擴展至包住其子元素,在這個新的BFC中浮動元素又迴歸到頁面的常規流之中了。

 

使用BFC避免文字環繞

如上圖所示,對於浮動元素,可能會形成文字環繞的狀況(Figure1),但這並非咱們想要的佈局(Figure2纔是想要的)。要解決這個問題,咱們能夠用外邊距,但也能夠用BFC。

假設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元素的文本(行盒子)卻移位了,行盒子水平變窄來給浮動元素騰出了空間。隨着文本的增長,最後文本將環繞在浮動元素之下,由於那時候行盒子再也不須要移位,也就成了圖figure1的樣子。

再回顧一下W3C的描述:

在BFC上下文中,每一個盒子的左外側緊貼包含塊的左側(從右到左的格式裏,則爲盒子右外側緊貼包含塊右側),甚至有浮動也是如此(儘管盒子裏的行盒子 Line Box 可能因爲浮動而變窄),除非盒子建立了一個新的BFC(在這種狀況下盒子自己可能因爲浮動而變窄)。

於是,若是p元素建立了新的BFC那它就不會再緊貼包含塊的左側了。

 

在多列布局中使用BFC

若是咱們建立一個佔滿整個容器寬度的多列布局,在某些瀏覽器中最後一列有時候會掉到下一行。這多是由於瀏覽器四捨五入了列寬從而因此列的總寬度會超出容器。但若是咱們在多列布局中的最後一列裏建立一個新的BFC,它將老是佔據其餘列先佔位完畢後剩下的空間。

例如:

<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和IFC的區別

IFC佈局規則

在行內格式化上下文中,框(boxes)一個接一個地水平排列,起點是包含塊的頂部。水平方向上的 marginborder和 padding在框之間獲得保留。框在垂直方向上能夠以不一樣的方式對齊:它們的頂部或底部對齊,或根據其中文字的基線對齊。包含那些框的長方形區域,會造成一行,叫作行框。

 


GFC

GFC(GridLayout Formatting Contexts)直譯爲"網格佈局格式化上下文",當爲一個元素設置display值爲grid的時候,此元素將會得到一個獨立的渲染區域,咱們能夠經過在網格容器(grid container)上定義網格定義行(grid definition rows)和網格定義列(grid definition columns)屬性各在網格項目(grid item)上定義網格行(grid row)和網格列(grid columns)爲每個網格項目(grid item)定義位置和空間。

那麼GFC有什麼用呢,和table又有什麼區別呢?首先一樣是一個二維的表格,但GridLayout會有更加豐富的屬性來控制行列,控制對齊以及更爲精細的渲染語義和控制。

FFC

FFC(Flex Formatting Contexts)直譯爲"自適應格式化上下文",display值爲flex或者inline-flex的元素將會生成自適應容器(flex container),惋惜這個牛逼的屬性只有谷歌和火狐支持,不過在移動端也足夠了,至少safari和chrome仍是OK的,畢竟這倆在移動端纔是王道。

Flex Box 由伸縮容器和伸縮項目組成。經過設置元素的 display 屬性爲 flex 或 inline-flex 能夠獲得一個伸縮容器。設置爲 flex 的容器被渲染爲一個塊級元素,而設置爲 inline-flex 的容器則渲染爲一個行內元素。

伸縮容器中的每個子元素都是一個伸縮項目。伸縮項目能夠是任意數量的。伸縮容器外和伸縮項目內的一切元素都不受影響。簡單地說,Flexbox 定義了伸縮容器內伸縮項目該如何佈局。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息