iT邦幫忙

2021 iThome 鐵人賽

0
自我挑戰組

登堂入室!前端工程師的觀念技術 _30_ 題系列 第 28

27. 解釋 CSS 的 BFC(Block Formatting Context)

Formatting Context


所有的HTML元素,在CSS裡都可以視為box(盒子),在Normal Flow裡的boxes會具備formatting context。

Everything on a page is part of a formatting context, or an area which has been defined to lay out content in a particular way.

在一個頁面上,每個元素都是formatting context的一部份,而區域環境內的元素會依照特定的方式排版。他們可能是block或inline,且不會同時具備兩者。

( Formatting → 格式 / Context → 區域環境;上下文 )

CSS的Formatting Context包含這幾種:

  1. BFC(Block formatting context) : 塊狀物件(block-level boxes)屬於block formatting context
  2. IFC(Inline formatting context) : 行內物件(inline-level boxes)屬於inline formatting context
  3. FFC(Flex formatting context)
  4. GFC(Grid formatting context)

BFC(Block Formatting Context)


BEC的性質(在水平模式):

“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).” - 9.4.1

引用自 Block and inline layout in normal flow - CSS: Cascading Style Sheets | MDN

(預設為水平方向排列的情況)

  1. 一個接著一個的垂直排列。
  2. 順序是由上而下。
  3. 兩個同級box的垂直距離由'margin'屬性決定。
  4. 每個外層box的左外緣,接合內部box的左緣。

Margin collapsing 邊界重疊

if you have an element with a top margin immediately after an element with a bottom margin, rather than the total space being the sum of these two margins, the margin collapses, and so will essentially become as large as the larger of the two margins.

邊界重疊是指,當兩個block元素相鄰,如果同時設定了一個 Block 的 下外距 ( margin-bottom ) ,和另一個 Block 的 上外距 ( margin-top ) , 兩個block的距離不會是外距的總和,而是較大的那個外距。

舉例來說:

// html
<div class="div div1">
  margin bottom = 50px; 
</div>
<div class="div div2">
  margin top = 50px; margin bottom = 0; 
</div>
<div class="div div3">
  margin top = 50px
</div>
// css
.div {
  border: 2px solid blue;
}
.div1 {
  margin-bottom: 50px;
}
.div2, .div3 {
  margin-top: 50px;
}

執行結果:
https://ithelp.ithome.com.tw/upload/images/20211003/20129476ajFYCoQHek.png
可以看到,
div1雖然設定了底部的外距,但因為div2也設定了上方的外距,所以他們之間的距離只有50px。


in-flow & Out of flow

所有的元素都是in-flow,除了 :

  • floated items
  • items with position: absolute (including position: fixed)
  • the root element (html)

而這些Out of flow的物件,會創建一個新的BFC,
所以也可將他們視為一個小範圍的獨立布局(mini layout)。

→ 因為根元素(html)是Out of flow,所以整個document本身就會建立BFC。

設定為 float 或絕對定位的元素,不會產生邊界重疊。

舉例:

<!-- Out of flow -->
<div class="outer">
  <div class="float">Hello, I'm a floating box.</div>
  lements participating in a BFC use the rules outlined by the CSS Box Model, which defines how an element's margins, borders, and padding interact with other blocks in the same context.
</div>

<div class="outer">
  <div class="float">Hello, I'm a floating box.</div>
  lements participating in a BFC
</div>
// scss
.outer {
  border: 2px solid red;
  width: 300px;
  padding: 10px;
  margin-top: 10px; 
  .float {
    float: left;
    background: black;
    color: white;
    width: 100px;
  }
}

執行結果:
https://ithelp.ithome.com.tw/upload/images/20211003/20129476oairw1yVYC.png

一個容器的內容會決定block的高度,所以在第一個div裡,外層的div還剛好能包裹住內層的div。

然而,因為float本身會導致Out of flow,所以如果容器的高度不超過浮動(float)的物件,
那可能就會像下方的div一樣,外層的div會無法包覆住內層的div。

比較容易的解決辦法,除了硬性規定height高度外,
可以在外部的div加入overflow:auto; :

// scss
.outer {
  border: 2px solid red;
  width: 300px;
  padding: 10px;
  margin-top: 10px; 
  overflow: auto;   // 當內容溢出flow時,自動調整高度
  .float {
    float: left;
    background: black;
    color: white;
    width: 100px;
  }
}

這樣看起來應該比較美觀了:
https://ithelp.ithome.com.tw/upload/images/20211003/20129476Vn8g8Y2070.png

提供範例的 codepen完整程式碼

最後,如果想要建立一個全新的BFC,
除了上面舉例的作法外,也可以參考MDN的其他範例。

【如內文有誤還請不吝指教>< 並感謝閱覽至此的各位:D 】

參考資料

---正文結束---


上一篇
26. Redux 的用途 & 入門實作 (下)
下一篇
28. 解釋 CSS Box Model ( box-sizing )
系列文
登堂入室!前端工程師的觀念技術 _30_ 題31

尚未有邦友留言

立即登入留言