BFC 淺析

先前在學(xué)習(xí)CSS float時,有同學(xué)提到了BFC這個詞,作為求知好問的好學(xué)生,哪里不懂查哪里,那么今天就來研究一下BFC究竟是什么。

BFC 是什么?

首先,BFC(block formatting context),中文直譯:塊格式化上下文。BFC的概念,無論是在W3C CSS2.1官方文檔,還是在MDN文檔中,都是十分難讀懂的。再翻閱了大量博客后,首先必須了解,視覺格式化模型這個概念:

視覺格式化模型

CSS 視覺格式化模型(visual formatting model)是用來處理文檔并將它顯示在視覺媒體上的機(jī)制。這是 CSS 的一個基礎(chǔ)概念。 視覺格式化模型根據(jù) CSS 盒模型為文檔的每個元素生成 0,1 或多個盒。

  • 盒尺寸:明確指定,受限或沒有指定
  • 盒類型:行內(nèi)(inline), 行內(nèi)級別(inline-level), 原子行內(nèi)級別(atomic inline-level), 塊(block)盒;
  • 定位方案(positioning scheme): 常規(guī)流,浮動或絕對定位;
  • 樹中的其它元素: 它的子代與同代;
  • 視口(viewport) 尺寸與位置;
  • 內(nèi)含圖片的固定尺寸;
  • 其它信息。

CSS 視覺格式化模型的一部分工作是從文檔元素生成盒。生成的盒擁有不同類型,并對視覺格式化模型的處理產(chǎn)生影響。生成盒的類型取決于 CSS 屬性 display

—— MDN - 視覺格式化模型

對于這個概念,可以簡單理解為,頁面文檔在瀏覽器(視覺媒體)上的顯示,是通過一定的模型構(gòu)建的,就如同我們在word中寫文章時,可以進(jìn)行排版一樣,這些模型就是幫助我們在瀏覽器中構(gòu)建網(wǎng)頁內(nèi)容的排版。那么頁面中的元素,就會根據(jù)這些模型生成一個個的盒子,這就是我們頁面中的最基本的單位。

BFC基本描述

塊格式化上下文(block formatting context) 是Web頁面的可視CSS渲染的一部分。它是塊盒子的布局發(fā)生及浮動體彼此交互的區(qū)域。

——MDN - 塊格式化上下文

再看到MDN對于BFC的描述,可以理解為頁面中的塊盒(block boxes)所使用的的渲染模型就是BFC,當(dāng)元素滿足一定條件時,我們稱之為觸發(fā)了BFC,使其滿足這個渲染模型的規(guī)范。

那么問題來了,什么是塊盒(block boxes)?

塊盒(block boxes)

塊級元素與塊盒(Block-level elements and block boxes)

當(dāng)元素的 CSS 屬性 displayblock, list-itemtable 時,它是塊級元素 block-level 。塊級元素(比如<p>)視覺上呈現(xiàn)為塊,豎直排列。

塊級盒參與(塊格式化上下文 block formatting context)。每個塊級元素至少生成一個塊級盒,稱為主要塊級盒(principal block-level box)。一些元素,比如<li>,生成額外的盒來放置項目符號,不過多數(shù)元素只生成一個主要塊級盒。

主要塊級盒將包含后代元素生成的盒以及生成的內(nèi)容。它也是可以使用(定位方案 positioning scheme)的盒。

Block boxes
Block boxes

一個塊級盒可能也是一個塊容器盒。塊容器盒(block container box) 只包含其它塊級盒,或生成一個行內(nèi)格式化上下文(inline formatting context),由此只包含行內(nèi)盒。注意塊級盒與塊容器盒概念不同。 前者描述元素跟它的父元素與兄弟元素之間的表現(xiàn),后者描述元素跟它的后代之間的影響。有些塊級盒,比如表格,不是塊容器盒。相反,一些塊容器盒,比如非替換行內(nèi)塊及非替換表格單元格,不是塊級盒。

同時是塊容器盒的塊級盒稱為塊盒(block boxes)。(譯注:塊級盒與塊盒名字相近,注意分別-

—— MDN - 視覺格式化模型

根據(jù)MDN文檔,這里我整理了關(guān)于盒子的三個概念:

  1. Block-level boxes

    塊級盒(Block-level boxes)指由塊級元素構(gòu)成的盒子,每個塊級元素至少會生成一個盒子,我們稱其為主塊級盒子。塊級盒描述塊級元素跟它的父元素和兄弟元素的表現(xiàn)。

  2. Block containing boxes

    塊容器盒(Block containing boxes)指只包含其他塊級盒的盒子,或指生成行內(nèi)格式化上下文(inline fomatting context)的盒子,由此生成的盒子只包含行內(nèi)盒(inline boxes)。其描述了元素與后代之間的影響。

  3. Block boxes

    塊盒(Block boxes)指既是塊級盒,又是塊容器盒的盒子。

總的來看,塊盒屬于一個復(fù)雜概念的集合,當(dāng)一個盒子既包含塊級盒又包含塊級容器的概念時,它就是一個塊盒。其中,包含了塊級元素與父親、兄弟、子代關(guān)系的描述和影響,還涉及了其他視覺格式化的內(nèi)容。因此,BFC可以說是一種CSS 渲染的表現(xiàn)形式。

對于BFC,我們還需要了解其特性及觸發(fā)條件:

BFC特性&創(chuàng)建條件

特性:

  1. 內(nèi)部的Box會在垂直方向,從頂部開始一個接一個地放置。
  2. Box垂直方向的距離由margin決定。屬于同一個BFC的兩個相鄰Box的margin會發(fā)生疊加
  3. 每個元素的margin box的左邊,與包含塊border box的左邊相接觸(對于從左往右的格式化,否則相反)。即使存在浮動也是如此。
  4. BFC的區(qū)域不會與float box疊加。
  5. BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素,反之亦然。
  6. 計算BFC的高度時,浮動元素也參與計算。

——《CSS之BFC詳解

創(chuàng)建條件:

塊格式化上下文由以下之一創(chuàng)建:

  • 根元素或其它包含它的元素
  • 浮動 (元素的 float 不是 none)
  • 絕對定位的元素 (元素具有 positionabsolutefixed)
  • 內(nèi)聯(lián)塊 inline-blocks (元素具有 display: inline-block)
  • 表格單元格 (元素具有 display: table-cell,HTML表格單元格默認(rèn)屬性)
  • 表格標(biāo)題 (元素具有 display: table-caption, HTML表格標(biāo)題默認(rèn)屬性)
  • 塊元素具有overflow ,且值不是 visible
  • display:flow-root

——MDN - 塊格式化上下文

BFC 可以用來做什么?

1. 解決margin重疊的問題

根據(jù)BFC的特性,同一個BFC下的兩個相鄰的盒子會出現(xiàn)垂直margin重疊的問題,這個問題會影響我們對頁面布局的控制,通常我們可以為其中一個盒子添加一個父元素,并使其觸發(fā)BFC,即可解決這個問題:

margin重疊

2. 浮動帶來的布局問題

根據(jù)前面其他作者總結(jié)的BFC特性的第三條和第四條,我們知道在同一個BFC下即使有元素浮動,BFC下元素的最左邊邊緣總是會與包含它的盒子左邊相接觸,那么就會出現(xiàn)浮動元素遮蓋了其他元素的情況。BFC還有一條重要特性:BFC的區(qū)域不會與float box 重疊。試想,在一個BFC,如果存在一個float元素,和一個div,浮動元素會遮蓋住div,此時,如果給這個div構(gòu)建一個新的BFC,由于BFC特性,內(nèi)外不相互影響,此時div會被float元素擠開。

比如下面這個例子,綠色盒子會因為浮動遮蓋住紅色的盒子,但由于兩個盒子都在同一個BFC(body元素)下,根據(jù)BFC特性,紅色盒子會與包含塊相接,此時只要讓紅色盒子觸發(fā)BFC,我們?yōu)榧t色盒子添加一個觸發(fā)BFC的條件overflow:hidden,此時紅色盒子由于BFC的特性隔離開綠色,這樣我們就可以通過float元素的方式實現(xiàn)兩欄布局。

布局問題

3. 清除浮動

這里就要說到我們常見的浮動元素引起的高度坍塌的問題。由于浮動特性,浮動元素會脫離父元素,我們是否可以通過觸發(fā)BFC來解決高度坍塌的問題呢?

根據(jù)特性的第6條,在觸發(fā)BFC后,這個盒子的高度將包含浮動元素的高度,在計算時,浮動元素會參與高度計算,我們可以理解為,當(dāng)一個父元素中包含了浮動元素,而浮動元素超出了父元素,此時我們?yōu)楦冈貏?chuàng)建BFC,那么浮動元素就會包裹進(jìn)這個BFC解決了父元素中高度塌陷的問題。

如下面的例子,div.parent包含了兩個div.child,而兩個div由于賦予了float:left使其浮動,導(dǎo)致了div.parent高度的坍塌,此時我們給div.parent添加一個overflow:hidden屬性值,使div.parent觸發(fā)BFC,由于BFC下的盒子會包含浮動元素的高度,因此盒子就被撐了起來,高度塌陷的問題也就得到了解決。

清除浮動

除了上面的清除浮動用到了BFC的一些特性外,還有一些其他的清除浮動的技巧,這里就不再做深入討論。

其他

在學(xué)習(xí)BFC過程中,主要借鑒了一些博客文章及MDN的說明,由于自己的書面表達(dá)能力有限,這篇文章主要用于記錄學(xué)習(xí)BFC的過程,如有表述不清的地方還請見諒。

此外,為了補充疏漏的地方,增加W3C官方文檔的閱讀。不過官方文檔中BFC及相關(guān)概念大多為描述,沒有非常確切的定性,所以這里只放出來作為參考。由于自己的英語水平有限,如有描述不當(dāng)?shù)牡胤剑堃訵3C CSS官方文檔為準(zhǔn)。

BFC(block formatting context)的官方描述

我們來看看W3C CSS2.1文檔中關(guān)于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.

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). 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).

簡單的人肉+谷歌翻譯:

浮動元素、絕對定位元素、塊容器(比如 inline-blocks,table-cells,table-captions)及overflow值不為visable(除非該值已被傳到視口)的塊盒(block boxes),都會為其內(nèi)容建立新的塊格式化上下文(BFC)。

在一個BFC中,盒子將會垂直的從包含塊(containing block)的頂部一個接一個的向下布置,兄弟元素之間的垂直距離將由margin屬性確定。在BFC中,兩個相鄰的塊級盒子(block-level boxes)之間的垂直邊距(vertical margins)將會坍塌。

在一個BFC中,每個盒子的左外邊緣會接觸包容塊的左邊緣(對于從右往左的格式,則相反)。即便是在浮動floats情況下也是如此(盡管盒子的線框可能由于浮動而收縮),除非盒子建立了一個新的BFC(這種情況下,盒子自身可能會因為浮動變得更窄)。

格式化上下文(formatting context)

CSS 2.1 - 9.4 Normal flow

Boxes in the normal flow belong to a formatting context, which may be block or inline, but not both simultaneously.

Block-level boxes participate in a block formatting context. Inline-level boxes participate in an inline formatting context.

簡單的人肉+谷歌翻譯:

正常流中屬于格式化上下文的盒子,可以是塊或者內(nèi)聯(lián),但不能同時存在。塊級盒參與塊級格式化上下文,行內(nèi)級參與行級格式上下文。

包含塊(containing block)

CSS 2.1 W3C 文檔:

In CSS 2.1, many box positions and sizes are calculated with respect to the edges of a rectangular box called a containing block. In general, generated boxes act as containing blocks for descendant boxes; we say that a box "establishes" the containing block for its descendants. The phrase "a box's containing block" means "the containing block in which the box lives," not the one it generates.

Each box is given a position with respect to its containing block, but it is not confined by this containing block; it may overflow.

簡單的人肉+谷歌翻譯:

在 CSS2.1中,許多盒子的定位(positions)和尺寸(size)被用來計算相對于矩形盒子的邊緣,這種矩形盒子我們稱其為包容塊(containing block)。通常,生成的盒子將作為后代盒子的包含塊,我們稱其一個盒子為其后代建立(establishes)包容塊。“一個盒子的包容塊(a box's containning block)“指”這個盒子所在的包容塊“,而不是指這個盒子產(chǎn)生的塊。

塊級盒子(block-level boxes)

Block-level elements are those elements of the source document that are formatted visually as blocks (e.g., paragraphs). The following values of the 'display' property make an element block-level: 'block', 'list-item', and 'table'.

Block-level boxes are boxes that participate in a block formatting context. Each block-level element generates a principal block-level box that contains descendant boxes and generated content and is also the box involved in any positioning scheme. Some block-level elements may generate additional boxes in addition to the principal box: 'list-item' elements. These additional boxes are placed with respect to the principal box.

Except for table boxes, which are described in a later chapter, and replaced elements, a block-level box is also a block container box. A block container box either contains only block-level boxes or establishes an inline formatting context and thus contains only inline-level boxes. Not all block container boxes are block-level boxes: non-replaced inline blocks and non-replaced table cells are block containers but not block-level boxes. Block-level boxes that are also block containers are called block boxes.

The three terms "block-level box," "block container box," and "block box" are sometimes abbreviated as "block" where unambiguous.

簡單的人肉+谷歌翻譯:

塊級元素是源文檔中作為塊被視覺格式化的元素(比如:paragraphs)。display屬性作為元素塊級的表示,其值有blocklist-itemtable

塊級元素是參與BFC的盒子。每一個塊級元素會生成一個主要塊級元素盒(principal block-level box),盒中包含后代盒子和生成的內(nèi)容,同時這個盒也包含任意定位方案。除了主塊級元素盒外,一些塊級元素也可能產(chǎn)生額外的盒子,比如:list-item元素。這些額外的盒子會被放置在相對主盒的地方。

除了后面章節(jié)描述的表格盒(table boxes)和替換元素外,塊級元素盒(block-level box)同時也是一個塊容器盒(block container box)。塊容器盒要么只包塊級盒,或建立內(nèi)聯(lián)格式化上下文(inline formatting)的情況下只包含內(nèi)聯(lián)級盒子(inline-level boxes)。并非所有塊容器盒都是塊級盒,不包含內(nèi)聯(lián)盒子和表單cell(table cell)的是塊容器(block container),而不是塊級盒(block-level boxes)。既是塊級盒(block-level boxes)同時也是塊容器(block container)的稱為塊盒(block boxes)。

塊級盒(block-level block),塊容器盒(block container box),塊盒(block box)這三個術(shù)語有時會縮寫為明確的:塊(block)

參考:

  1. CSS之BFC詳解
  2. W3C CSS2.1 spec 9 Visual formatting model
  3. 扒一下W3C規(guī)范里的BFC和IFC
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補...
    _Yfling閱讀 13,776評論 1 92
  • 什么是BFC BFC全稱是Block Formatting Context,即塊格式化上下文。它是CSS2.1規(guī)范...
    陌客百里閱讀 536評論 3 4
  • 轉(zhuǎn)載自(http://web.jobbole.com/83274/) BFC BFC全稱是Block Format...
    居客俠閱讀 2,148評論 0 20
  • BFC全稱是Block Formatting Context,即塊格式化上下文。它是CSS2.1規(guī)范定義的,關(guān)于C...
    xf0128閱讀 344評論 0 0
  • 在普通流中的盒子會參與一種格式上下文,這個盒子可能是塊盒也可能是行內(nèi)盒,但不可能同時是塊盒又是行內(nèi)盒。塊級盒參與塊...
    出云月閱讀 262評論 0 0