1. 程式人生 > >BFC (塊級格式化上下文)

BFC (塊級格式化上下文)

per begin ria 先後 methods 原理 clearing lol 隔離

block formatting contexts

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.

浮動、絕對定位的元素、塊容器(例如inline塊、表格單元格和表標題)等非塊盒,和“overflow”不為“visible”的塊容器(除非這個值被傳播到viewport中)會它們的內容建立新的塊級格式化上下文。

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.
在塊級格式化上下文中,元素框從包含塊的頂部一個接一個地放置,margin屬性決定了兩個兄弟元素間的垂直距離,在同一塊級格式化上下文中的相鄰塊級盒子之間的垂直margin會
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). This is true even in the presence of floats (although a box‘s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).

在一個塊格式化上下文中,每個框的左外邊緣都觸及了包含塊的左邊緣(右到左的格式,右邊緣的觸摸)。即使在浮動的情況下也是如此(盡管一個框的行框可能會由於浮動而收縮),除非該框建立一個新的塊格式化上下文(在這種情況下,由於浮動,box本身可能會變得更窄)。

Inline formatting contexts

An inline formatting context is established by a block container box that contains no block-level boxes. In an inline formatting context, boxes are laid out horizontally, one after the other, beginning at the top of a containing block. Horizontal margins, borders, and padding are respected between these boxes. The boxes may be aligned vertically in different ways: their bottoms or tops may be aligned, or the baselines of text within them may be aligned. The rectangular area that contains the boxes that form a line is called a line box.一內聯格式化上下文由一個沒有包含塊級元素框的塊級容器建立,在一個內嵌的格式環境中,框被水平地放置,一個接一個,從一個包含塊的頂部開始。在這些框之間,橫向的邊距、邊距和內邊距都很受尊重。這些框可以以不同的方式垂直對齊:它們的底部或頂部可以對齊,或者它們之間的文本基線可以對齊。包含組成直線的方框的矩形區域稱為線框。




  • 普通流(Normal Flow)
在普通流中,元素按照其在 HTML 中的先後位置至上而下布局,在這個過程中,行內元素水平排列,直到當行被占滿然後換行,塊級元素則會被渲染為完整的一個新行, 除非另外指定,否則所有元素默認都是普通流定位,也可以說,普通流中元素的位置由該元素在 HTML 文檔中的位置決定。

一. BFC 是什麽?

有了上面的基礎後,可以正式介紹 BFC 了。從樣式上看,具有 BFC 的元素與普通的容器沒有什麽區別,但是從功能上,具有 BFC 的元素可以看作是隔離了的獨立容器,容器裏面的元素不會在布局上影響到外面的元素,並且 BFC 具有普通容器沒有的一些特性,例如可以包含浮動元素,清除浮動的方法(如 overflow 方法)就是觸發了浮動元素的父元素的 BFC ,使到它可以包含浮動元素,從而防止出現高度塌陷的問題。簡單來說,BFC 就是一種屬性,這種屬性會影響著元素的定位以及與其兄弟元素之間的相互作用。可以把它想象成一個大箱子,裏面裝著很多元素,箱子可以隔開裏面的元素和外面的元素。好像JS中的閉包,保護其中的元素。它可以包含浮動元素,可以阻止margin折疊,可以防止元素被浮動元素覆蓋……eg:

二.如何觸發 BFC

它至少滿足以下條件之一:
  • float 的值不為 none
  • position 的值不為 static 或 relative
  • display 的值為 table-cell、table-caption、inline-block、flex 或 inline-flex
  • overflow 的值不為 visiable
  • 對於 display:table 的元素,產生 block formatting contexts 的是匿名框而不是 display:table。

三.BFC有哪些作用:

  • 自適應兩欄布局
  • 可以阻止元素被浮動元素覆蓋
  • 可以包含浮動元素——清除內部浮動
  • 分屬於不同的BFC時可以阻止margin重疊


1.利用BFC可以消除Margin Collapse

在正常情況下,在一個容器內的所有box將會由上至下依次垂直排列,即我們所說的一個元素占一行,並切垂直相鄰的距離(即margin)是由各自的margin決定的,而不是兩個margin的疊加。

讓我們看一個例子:紅色的div包含三個綠色的p元素。

HTML代碼:

CSS代碼:

理想情況下,我們會認為p標簽之間的margin應該是它們的和(20px),但實際上卻是10px.這其實是collapsing margins。

結果如下:

技術分享圖片

這似乎讓人有點困惑,BFC導致了margin collapse,而現在又要用它來解決margin cllapse.但是始終要記住一點:只有當元素在同一個BFC中時,垂直方向上的margin
才會clollpase.如果它們屬於不同的BFC,則不會有margin collapse.因此我們可以再建立一個BFC去阻止margin collpase的發生。

現在HTML變成:

CSS也有改變:

現在的結果為:

技術分享圖片

由於第二個p元素和第三個p元素屬於不同的BFC,因此避免了margin collapse.

2.利用BFC去容納浮動元素

我相信大家經常會遇到一個容器裏有浮動元素,但是這個容器的高度卻是0的場景,如下圖:

看下面的例子:

HTML:

CSS:

結果:

技術分享圖片

在上邊的情形中,container是不會有高度的,因為它包含了浮動元素。通常我們解決這個問題的辦法是利用一個偽元素去實現clear fix,但是現在我們有了更好的解決辦法,即利用BFC,因為它夠容納浮動元素的。
我們現在讓container形成BFC規則,結果如下:

結果:

技術分享圖片

3.利用BFC阻止文本換行

有時候,確切的說大多數情況(若沒有特殊設置),文本將會環繞浮動元素(如Figure 1),
但有時候這並不是我們期望的,我們想要的是Figure2。

技術分享圖片

往往可能大家都會選擇利用margin-left來強行讓p的容器有一個左邊距,而距離恰好為Floated div的寬度,但現在我們可以利用BFC更好的解決這個問題。

首先讓我們了解一下文本換行的原理吧:

技術分享圖片

在Figure1中,整個p元素實際上是處於上圖中的黑色區域,p元素沒有移動是因為它在浮動元素的下方。但實際上p作為行塊級別的元素(相對於行內文本)卻發生了移動,因為要給float元素’騰’位置,而隨著文本的增加,文本高度超過浮動元素的部分則不會在水平方向上收縮內部距離,因此看起來像是環繞。

如圖:

技術分享圖片

在解決這個問題之前,我們先來看一下W3C的規範在這方面的描述:

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). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).

W3C為這種情況提供了一個解決方案:unless the box establishes a new block formatting context,即為p建立BFC。

結果:

技術分享圖片

BFC (塊級格式化上下文)