【前端幫幫忙】第8期 關於BFC,你須要瞭解的

BFC是耳熟能詳的一個東西了,常常聽到,其實在項目中也常常用到,好比最經常使用的清除浮動,自適應兩欄佈局等等。只是都沒有去深究其原理和相關的知識點,今天就一塊兒來好好學習一下吧。css

要明白BFC是什麼,咱們要先來了解幾個相關的概念。html

盒模型

MDN對其描述以下:前端

當對一個文檔進行佈局(lay out)的時候,瀏覽器的渲染引擎會根據標準之一的CSS基礎盒模型(CSS basic box model),將全部元素表示爲一個個矩形的盒子(box)。CSS決定這些盒子的大小、位置和以及屬性(例如顏色、背景、邊框尺寸...)。css3

每一個盒子由四個部分(或稱區域)組成,其效用由它們各自的邊界(Edge)所定義(原文:defined by their respective edges,可能意指容納、包含、限制等)。如圖,與盒子的四個組成區域相對應,每一個盒子有四個邊界:內容邊界 Content edge、內邊距邊界 Padding Edge、邊框邊界 Border Edge、外邊框邊界 Margin Edge。瀏覽器

咱們在瀏覽器的控制檯也能夠很清楚的看到頁面的每個元素(除了單獨的文本元素),其實都是一個盒子:安全

更加詳細的介紹能夠參考MDN或者W3C規範的描述:bash

www.ayqy.net/doc/css2-1/…ide

視覺格式化模型

MDN 對其描述以下:佈局

CSS視覺格式化模型(visual formatting model)是用來處理和在視覺媒體上顯示文檔時使用的計算規則。該模型是CSS的基礎概念之一。post

視覺格式化模型會根據CSS盒子模型將文檔中的元素轉換爲一個個盒子,每一個盒子的佈局由如下因素決定:

  • 盒子的尺寸:精確指定、由約束條件指定或沒有指定
  • 盒子的類型:行內盒子(inline)、行內級盒子(inine level)、原子行內級盒子(atomic inine-level)、塊盒子(block)
  • 定位方案(position scheme):普通流定位、浮動定位或絕對定位
  • 文檔樹中的其餘元素:即當前盒子的子元素或兄弟元素
  • 視口尺寸與位置
  • 所包含的圖片的尺寸
  • 其餘的某些外部因素

關於不一樣類型盒子的介紹,你們能夠直接看MDN,寫的很詳細了,這裏就再也不闡述。這邊着重講下定位方案

定位方案

一旦生成了盒子,CSS引擎就須要定位它們以完成佈局。在定位的時候,瀏覽器會根據元素的盒類型和上下文對這些元素進行定位,能夠說盒就是定位的基本單位。定位時有三種定位方案,分別是:常規流(即普通流)、浮動流以及絕對定位。

常規流(Normal flow)

  • 在常規流中,盒子一個接着一個排列;
  • 塊級格式化上下文裏面,它們豎着排列;
  • 行內格式化上下文裏面,它們橫着排列;
  • positionstaticrelative,而且floatnone時,會觸發常規流
  • 對於靜態定位(static positioning),position: static,盒的位置是常規流佈局裏的位置;
  • 對於相對定位*(relative positioning),position: relative,盒偏移位置右這些屬性定義:topbottomleftright即便有偏移,仍然保留原有的位置,其餘常規流不能佔用這個位置。

浮動(Floats)

  • 盒成爲浮動盒(floating boxes);
  • 它定位於當前行的開頭或末尾;
  • 致使常規流環繞在它的周邊,除非設置clear屬性;

絕對定位(Absolute positioning)

  • 絕對定位方案,盒從常規流中被移除,不影響常規流的佈局;
  • 它的定位相對於它的包含塊,相關CSS屬性:topbottomleftright
  • 對於position: absolute,元素定位相對於最近的一個relativeabsolutefixed的父元素,若是沒有則相對於body

FC(Formatting context)

Formatting context是W3C CSS2.1規範中的一個概念。它是頁面中一塊渲染區域,而且有一套渲染規則,它決定了其子元素將如何定位,以及和其餘元素的關係和相互做用。最多見的Formatting context有Block formatting context(簡稱BFC)和Inline formatting context(簡稱IFC)。

CSS2.1中只有BFCIFC,CSS3中還增長了GFCFFC。咱們主要來說下BFC

好了,接下來輪到咱們的主角BFC出場了。

BFC是什麼

BFC(Block Formatting Context)直譯爲塊級格式化上下文。它是一個獨立的渲染區域,只有Box-level box參與,它規定了內部的Block-level box如何佈局,而且與這個區域外部絕不相干。

講了這麼多概念,說下本身的理解,若是有不對的地方,煩請指出,感激涕零。

  • 當咱們對一個頁面進行佈局的時候,瀏覽器的渲染引擎會根據CSS的盒模型將全部元素表示爲一個個盒子;
  • 盒子的定義是由視覺格式化模型來定義的,盒子的類型能夠分爲:行內盒子(inline)、行內級盒子(inine level)、原子行內級盒子(atomic inine-level)、塊盒子(block);
  • 接下來就是真正的佈局開始,瀏覽器會根據盒子的類型和所處的上下文來對這些元素進行定位,定位有3種方案,分別是:普通流、浮動流和絕對定位。
  • 普通流中的盒子就是屬於一個格式化上下文,多是塊或是行內(格式化上下文),但不能二者都是。塊級盒參與塊格式化上下文。行內級盒參與行內格式化上下文。

是否是能夠這樣理解:BFC就是普通流中的元素佈局定位時的一個執行環境?

BFC佈局規則

  • 內部的Box會在垂直方向,一個接一個的放置。(這邊不是很理解,內部的Box不是也可能有行內元素嗎?行內元素不是按水平方向來排列嗎?這邊可能還須要參考行內格式化上下文來理解,還有一個是writing-mode屬性。)
  • Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊
  • 每一個元素的margin box的左邊,與包含快border box的左邊相接觸(對於從左往右的格式化,不然相反),即便存在浮動也是如此(除非該盒創建了一個新的塊格式化上下文)
  • BFC的區域不會與float box重疊
  • BFC就是頁面上的一個隔離的獨立的容器,容器裏面的子元素不會影響到外面的元素,反之亦如此
  • 計算BFC的高度時,浮動元素也參與計算

如何建立BFC

  • 根元素
  • float屬性值不爲none
  • positionabsolutefixed
  • displayinline-blocktable-celltable-captionflexinline-flex
  • overflow不爲visible
  • ...

其實還有不少,這裏列出的是一些比較經常使用的,跟詳細的能夠看MDN

經過幾個實例來加深理解

1.自適應兩欄佈局

實現自適應兩欄佈局的方法有不少,可是我以爲BFC的方式應該是最簡單的了。

<body>
  <div class="container">
    <div class="side"></div>
    <div class="main"></div>
  </div>
</body>
複製代碼
.container {
  width: 400px;    
}

.side {
  float: left;
  width: 100px;
  height: 100px;
  background: lightpink;
}

.main {
  height: 300px;
  background: lightblue;
}
複製代碼

頁面截圖:

根據BFC佈局規則第3條:

每一個元素的margin box的左邊,與包含快border box的左邊相接觸(對於從左往右的格式化,不然相反),即便存在浮動也是如此(除非該盒創建了一個新的塊格式化上下文)

即便存在浮動元素sidemain的左邊依然會與包含快的左邊相接觸。

根據BFC佈局規則第4條:

BFC的區域不會與float box重疊

因此,咱們能夠給main建立一個新的BFC,這樣就不會跟浮動的side重疊了,它會根據包含塊的寬度和side的寬度,自動變窄。

main加上overflow: hidden

main {
  overflow: hidden;
}
複製代碼

再來看下效果:

2.清除內部浮動

<div class="parent">
  <div class="child"></div>
</div>
複製代碼
.parent {
   width: 200px;
   border: 2px solid blue;
   background: lightblue;
}

.child {
  float: left;
  width: 100px;
  height: 100px;
  border: 2px solid red;
  background: lightcoral;
}
複製代碼

頁面截圖:

能夠看到,因爲子元素設置了浮動,而父元素又沒有設置高度,致使父元素高度塌陷了:沒有自動被子元素的高度撐開。

根據BFC佈局規則第6條:

計算BFC的高度時,浮動元素也參與計算

咱們能夠給父元素parent觸發BFC,那麼它在計算高度時,內部的浮動元素也會參與計算。

.parent {
  overflow: hidden;
}
複製代碼

再看下效果:

3.阻止margin重疊

<div class="box">box</div>
<div class="box">box</div>
複製代碼
.box {
  width: 200px;
  height: 200px;
  margin: 100px;
  background: red;
}
複製代碼

頁面截圖:

根據BFC佈局規則第2條:

Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊

能夠看到,第一個div的下邊距跟第二個的上邊距發生了重疊。

重疊的結果按照以下規則計算:

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

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

咱們只要給其中一個div外層再包裹一層div,而後觸發其生成一個新的BFC,它們就不會發生重疊了。

<div class="box">box</div>
<div class="new-bfc">
  <div class="box">box</div>
</div>
複製代碼
.new-bfc {
  overflow: hidden;
}
複製代碼

頁面截圖:

還有不少其餘的例子,好比能夠避免文字環繞、多列布局等等,這裏就再也不一一列舉,你們有興趣的能夠本身多嘗試下,這裏有一個網址能夠在線演示,更加直觀, 連接地址:www.cnblogs.com/xiaohuochai…

建立BFC的新方式

咱們上面舉的例子都是經過overflow來建立BFC,可是其實這個方法會有兩個問題。

  1. 這些方法自己是有自身的設計目的的,因此在使用它們建立BFC時可能會存在一些反作用。例如,使用overflow建立BFC後,在某些狀況下可能會看到出現一個滾動條或者元素內容被裁切。這是因爲overflow屬性的設計是用來讓你告訴瀏覽器如何定義元素的溢出狀態的。瀏覽器執行了它最基本的定義。
  2. 另外一個問題是,即便在沒有出現反作用的狀況下,使用overflow也可能會使另外一個開發人員感到困惑。他們可能會各類猜測:這裏爲何要把overflow的值設爲autohidden?原來的開發人員這樣作的意義是什麼?原來的開發人員是想讓這裏出現滾動條嗎?

因此實際項目開發中,還須要根據項目的需求來選擇合適的方法,最好也能在代碼裏寫明註釋。

那有沒有什麼更好的方式呢?CSS工做組定義了一個新的屬性值:display: flow-root

你可使用display: flow-root安全的建立BFC,來解決上文中提到的各類問題:自適應兩欄佈局、清除內部浮動、阻止margin重疊等等。

caniuse上display: flow-root在各瀏覽器的兼容狀況,看圖:

目前來看,兼容性仍是差了一點。

有關於flow-root的詳細介紹能夠看這篇文章:www.w3cplus.com/css3/displa…

BFC概念理解

能夠想象一下,BFC就至關於咱們現實中的一個紙箱(盒子),箱子裏面的東西的放置(佈局)是不會受到外部其餘東西的影響的,它造成了一個獨立的封閉的區域。固然它裏面東西的放置(佈局)也不會影響到外面的東西。

最後

感謝您的閱讀,但願對你有所幫助,但願你能經過這篇文章能對BFC有一個比較全面的理解並能實際應用到項目開發中。本人水平有限,若是文中有不當的地方煩請指正,感激涕零。

關注

歡迎你們關注個人公衆號前端幫幫忙,一塊兒交流學習,共同進步。

參考:

視覺格式化模型

塊格式化上下文

前端精選文摘:BFC 神奇背後的原理

學習 BFC (Block Formatting Context)

[佈局概念] 關於CSS-BFC深刻理解

理解CSS佈局和BFC

什麼是BFC

相關文章
相關標籤/搜索