iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 18
1
自我挑戰組

前端新手進化史系列 第 18

視覺格式化模型-塊格式化上下文(BFC)

文章將陸續整理並更新至個人部落格


在先前的文章中提到不少次「BFC」,今天就來看看 BFC 是什麼,它又有什麼用處~

塊格式化上下文 (BFC)

摘自 W3C

In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the 'margin' properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.

In a block formatting context, each box's left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch).

也就是說,處在同一個 BFC 佈局環境中的元素(盒子),會有以下的佈局現象:

  • 元素從其包含塊(containing block)頂部開始,一個接一個呈現垂直排列。

  • 書寫方向由左至右,則元素(盒子)會貼齊包含塊左側

  • 兩個元素(盒子)之間的垂直距離,由元素的 margin 屬性決定。

  • 兩個相鄰(adjacent)的塊級盒子(block-level box)會發生邊距重疊(margin collapsing)


何時會建立 BFC

需留意的是,對於「什麼時候會建立一個 BFC」,在 W3C level 2.1 規範level 3 規範的定義有些微差異,但在 level 3 規範 有寫到「對於什麼時候會建立 BFC」並沒有一個「非常正式」的定義,有些條件是非常不嚴謹的,其僅列出「可能」情況。而在 MDN 上則有逐一詳細列出,可供參考。

因 level 3 規範在此處寫得不甚明確,因此以下將採用 2.1 規範的定義,再以 MDN 的定義輔助作為參考。

以下摘自 W3C 2.1 對於 BFC 的定義

Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

也就是說,下列這些情形會建立一個新的 BFC

  • float 屬性值不為 none

  • position 值為 absolutefixed

  • 塊容器盒子(block container box)但不是塊盒子(block box)的元素。

  • 塊盒子(block box),且 overflow 屬性值非 visible

註:
① absolutely positioned 是指 position 值為 abosolute 或 fixed。
② 塊容器盒子(block container box) 取決於元素 display 的內部顯示(inner display type),可參考 W3C 的 display 表
③ 同時為塊級盒子(block-level box) 與塊容器盒子(block container box)的盒子稱為塊盒子(block box)。


另外,一個值得留意的地方是,在 W3C level 3 對於 塊容器(block container) 的定義 中寫到

A block container box can both establish a block formatting context and an inline formatting context simultaneously.

也就是塊容器盒(block container box)是可以同時建立 BFCIFC 的。



接下來是 MDN 對於何時會建立塊格式化上下文(BFC)的定義。
摘自 MDN

下列方式會創建塊格式化上下文:

  • 根元素(<html>)
  • 浮動元素(元素的 float 不是 none)
  • 絕對定位元素(元素的 position 為 absolute 或 fixed)
  • 行內塊元素(元素的 display 為 inline-block)
  • 表格單元格(元素的 display 為 table-cell)
  • 表格標題(元素的 display 為 table-caption)
  • 匿名表格單元格元素(元素的 display 為 table、table-rowtable-row-group、table-header-group、table-footer-groupinline-table)
  • overflow 值不為 visible 的塊元素
  • display 值為 flow-root 的元素
  • contain 值為 layout、content 或 paint 的元素
  • flex 元素(display 為 flex 或 inline-flex 元素的直接元素)
  • grid 元素(display 為 grid 或 inline-grid 元素的直接元素)
  • 多列容器(column-count 或 column-width 不為 auto 的元素)
  • column-span 為 all 的元素始終會創建一個新的 BFC,即使該元素沒有包裹在一個多列容器中。



BFC 功用

可以解決:

  • float 元素的父容器塌陷問題。
  • 元素間的外邊距合併(margin collapsing)問題

解決 float 元素造成外容器塌陷問題

float 元素會導致外層容器的高度塌陷(若外層容器高度為 auto 且無其它比 float 元素高的子元素)。

<div class="container">
    <span>我是裝著 float 盒子的盒子(容器)</span>
    <div class="float">我是 float 盒子</div>
</div>
.container {
    width: 600px;
    background-color: #546E7A;
    border: 5px solid #333;
}

.float {
    float: left;
    width: 200px;
    height: 150px;
    background-color: #FFAB00;
    border:1px solid black;
    padding: 10px;
}    


此時可以使外層容器建立 BFC 來恢復高度。例如在外層容器加上 overflow: hidden,或 display: flow-root。


解決外距重疊(margin collapsing)問題

當元素與元素之間發生 margin collapsing 時,可透過讓元素建立 BFC,來解決 margin collapsing 問題。



結語

建議先釐清 W3C 規範中常出現的一些關鍵名詞的定義,對於視覺格式化模型的章節會挺有幫助的唷!
例如:

  • 包含塊(containing block)
  • 塊級元素(block-level element)
  • 塊元素(block element)
  • 塊容器(block container)
  • 行內級元素(inline-level element)
    • 行內元素(inline element)
    • 原子行內級元素(atomic inline-level element)
  • ...等等




塊格式化上下文(BFC)就此告一段落囉~
掰拉~


/images/emoticon/emoticon34.gif

此文章為學習筆記,如有錯誤的地方,麻煩告知~感謝!


參考資源

W3C-Appendix A: Glossary
W3C-Box Layout Modes: the display property
W3C-Collapsing margins
MDN-Block formatting context
MDN-overflow


上一篇
視覺格式化模型-格式化上下文
下一篇
視覺格式化模型 - 行內格式化上下文(IFC)
系列文
前端新手進化史30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言