理解CSS佈局和塊格式化上下文 什麼是BFC? 什麼情況下會創建BFC 常見應用場景 創建BFC的新方式

在進行html佈局及css編寫的時候,你是否遇到過這樣的問題:

  • 子元素設置浮動脫離文檔流後,父元素無法將其完全包裹
  • 子元素浮動實現兩欄佈局時,另一個子元素與浮動子元素重疊
  • 垂直方向的外邊距margin重疊
    ...

通常我們使用塊級格式化上下文(BFC)就能解決。

什麼是BFC?

塊格式化上下文(Block Formatting Context,BFC) 是Web頁面的可視化CSS渲染的一部分,是塊盒子的佈局過程發生的區域,也是浮動元素與其他元素交互的區域。

FC(formatting context)直譯過來是格式化上下文,它是頁面中的一塊渲染區域,有一套渲染規則,決定了其子元素如何佈局,以及和其他元素之間的關係和作用。

BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素,並且容器元素不會影響兄弟元素的佈局。

什麼情況下會創建BFC

  • 根元素或包含根元素的元素
  • 浮動元素(元素的 float 不是 none)
  • 絕對定位元素(元素的 position 爲 absolute 或 fixed)
  • 行內塊元素(元素的 display 爲 inline-block)
  • 表格單元格(元素的 display爲 table-cell,HTML表格單元格默認爲該值)
  • 表格標題(元素的 display 爲 table-caption,HTML表格標題默認爲該值)
  • 匿名錶格單元格元素(元素的 display爲 table、table-row、 table-row-group、table-header-group、table-footer-group(分別是HTML table、row、tbody、thead、tfoot的默認屬性)或 inline-table)
  • overflow 值不爲 visible 的塊元素
  • display 值爲 flow-root 的元素(新方式,文末會提及)
  • contain 值爲 layout、content或 strict 的元素
  • 彈性元素(display爲 flex 或 inline-flex元素的直接子元素)
  • 網格元素(display爲 grid 或 inline-grid 元素的直接子元素)
  • 多列容器(元素的 column-count 或 column-width 不爲 auto,包括 column-count 爲 1)
    column-span 爲 all 的元素始終會創建一個新的BFC,即使該元素沒有包裹在一個多列容器中。

常見應用場景

使父元素包含浮動元素

下面例子解釋如何讓浮動內容和父元素等高,清楚浮動負面影響

html

<div class="outer">
  <div class="float">I am a floated element.</div>
  I am text inside the outer box.
</div>

css

.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中的文字已經脫離文檔,如果文檔流文字過少,浮動元素就會溢出父元素邊緣。

這時候爲父元素設置overflow: auto或者除invisible默認值之外的任何有效值都能創建BFC解決這個問題,使父元素包含浮動元素

.outer {
  overflow: auto;
}

BFC防止垂直外邊距重疊

外邊距摺疊的規則是:當兩個塊級元素相鄰並且在同一個塊級格式化上下文時,它們垂直方向上的外邊距會產生重疊

html

<div class="outer">
  <p>I am paragraph one and I have a margin top and bottom of 20px</p>
  <p>I am paragraph two and I have a margin top and bottom of 20px</p>
</div>

css

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

由於p元素的邊緣和外部div上的邊距之間沒有內容,因此兩者將會合並,因此段落最終與框的頂部和底部齊平。我們在段落的上方和下方看不到任何灰色。如下圖:

當父元素設置了BFC之後,父元素與子元素p重疊區域將不再合併

.outer {
  background-color: #ccc;
  margin: 0 0 40px 0;
  overflow: auto;
}

BFC防止文本環繞

依然像上面例子文字環繞效果的佈局和樣式

html

<div class="outer">
  <div class="float">I am a floated element.</div>
  <div class="text">I am text...</div>
</div>

css

.float{
    float: left;
}

這時候如果不想要右側文字環繞浮動文字盒子,在左側div設置浮動的情況下,我可以通過使右邊div成爲BFC,使兩個兄弟div互相隔離、互不影響,從而達到去除文字環繞的效果。

.text {
  overflow: auto;
}

創建BFC的新方式

創建BFC的許多方法通常會帶來一些副作用,目前爲止似乎最安全的就是overflow屬性,但某些情況下我們不需要滾動條,此時滾動條就變成了這種方式的副作用,因此display有個新的屬性flow-root可以在任何需要創建BFC場景下使用,它並且不會帶來任何副作用。

flow-root瀏覽器兼容情況:

瀏覽器對此值的支持是有限的,如果要在不支持flex或網格佈局瀏覽器創建回退,瞭解BFC阻止浮動元素的負面影響十分必要。

PS:更多前端資訊、技術乾貨,請關注公衆號「前端新視界

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章