BFC原理詳解

一.BFC是什麼

在解釋 BFC 是什麼以前,須要先介紹 Box、Formatting Context的概念。css

1.BOX:CSS佈局的基本單位

BoxCSS佈局的對象和基本單位, 直觀點來講,就是一個頁面是由不少個 Box 組成的。元素的類型和 display 屬性,決定了這個 Box 的類型。 不一樣類型的 Box, 會參與不一樣的 Formatting Context(一個決定如何渲染文檔的容器),所以Box內的元素會以不一樣的方式渲染。讓咱們看看有哪些盒子:html

  • block-level box:display 屬性爲 block, list-item, table 的元素,會生成 block-level box。而且參與 block fomatting context;前端

  • inline-level box:display 屬性爲 inline, inline-block, inline-table 的元素,會生成 inline-level box。而且參與 inline formatting context;css3

  • run-in box: css3 中才有, 這兒先不講了。web

注:這裏補充一些block-level box一些知識canvas

1.1 block-level box

  • w3.org中對塊級元素的定義瀏覽器

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’.ide

大意:塊級元素是那種源文檔被格式化爲可視塊了的元素,而後使這個元素變成塊級元素的display屬性取值以下: ‘block’, ‘list-item’, 和 ‘table’。wordpress

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佈局

大意:塊級盒block-level box是這種參與了塊級排版上下文的一種盒子,每一個塊級元素都生成了一個包含後代盒子和生成的內容的主要塊級盒,而且這個盒子參與了任何定位的計算

  • block-level box 盒模型

圖片描述
圖片描述

  • block-level box特性

塊狀元素排斥其餘元素與其位於同一行,能夠設定元素的寬(width)和高(height),塊級元素通常是其餘元素的容器,可容納塊級元素和行內元素。

塊狀元素具備流體特性,即:在默認狀況下(非浮動、絕對定位等),水平方向會自動填滿外部的容器

2.Formatting context

Formatting context 是 W3C CSS2.1 規範中的一個概念。它是頁面中的一塊渲染區域,而且有一套渲染規則,它決定了其子元素將如何定位,以及和其餘元素的關係和相互做用。最多見的 Formatting context 有 Block fomatting context (簡稱BFC)和 Inline formatting context (簡稱IFC)。
CSS2.1 中只有 BFC 和 IFC, CSS3 中還增長了 GFC 和 FFC。

3.BFC定義

BFC(Block formatting context)直譯爲"塊級格式化上下文"。它是一個獨立的渲染區域,只有Block-level box參與, 它規定了內部的Block-level Box如何佈局,而且與這個區域外部絕不相干。

解釋:

BFC是 W3C CSS 2.1 規範中的一個概念,它決定了元素如何對其內容進行定位,以及與其餘元素的關係和相互做用。當涉及到可視化佈局的時候,Block Formatting Context提供了一個環境,HTML元素在這個環境中按照必定規則進行佈局。一個環境中的元素不會影響到其它環境中的佈局。好比浮動元素會造成BFC,浮動元素內部子元素的主要受該浮動元素影響,兩個浮動元素之間是互不影響的。這裏有點相似一個BFC就是一個獨立的行政單位的意思。也能夠說BFC就是一個做用範圍。能夠把它理解成是一個獨立的容器,而且這個容器的裏box的佈局,與這個容器外的絕不相干。

另外一個通俗點的解釋是:在普通流中的 Box(框) 屬於一種 formatting context(格式化上下文) ,類型能夠是 block ,或者是 inline ,但不能同時屬於這二者。而且, Block boxes(塊框) 在 block formatting context(塊格式化上下文) 裏格式化, Inline boxes(塊內框) 則在 inline formatting context(行內格式化上下文) 裏格式化。任何被渲染的元素都屬於一個 box ,而且不是 block ,就是 inline 。即便是未被任何元素包裹的文本,根據不一樣的狀況,也會屬於匿名的 block boxes 或者 inline boxes。因此上面的描述,便是把全部的元素劃分到對應的 formatting context 裏。

canvas會設立一個BFC,這也是最外層的formatting context了,問題的複雜性在於有些塊級盒內部也能夠產生BFC(至少它必須也能包含塊級盒),因而說BFC是能夠嵌套。不是全部塊級盒內部均可以產生BFC,好比說要是這盒裏面連塊級盒都沒有,都是行內盒那就產生IFC。不過,只要它的子節點裏面有一個塊級盒,它就產生BFC,那些行內元素,會自動套一個匿名的塊級行盒。

4.BFC的佈局規則

  • 內部的Box會在垂直方向,一個接一個地放置

  • Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊

  • 每一個元素的margin-box的左邊, 與包含塊border-box的左邊相接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此。

  • BFC的區域不會與float box重疊。

關於這條規則的幾點說明:

當容器有足夠的剩餘空間容納 BFC 的寬度時,全部瀏覽器都會將 BFC 放置在浮動元素所在行的剩餘空間內。
當 BFC 的寬度大於容器剩餘寬度時,最新版本的瀏覽中只有firefox會在同一行顯示,其它瀏覽器均換行。

  • BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素。反之也如此。

  • 計算BFC的高度時,浮動元素也參與計算

二.哪些元素會生成BFC

  • 根元素

  • float屬性不爲none

  • position爲absolute或fixed

  • display爲inline-block, table-cell, table-caption, flex, inline-flex

  • overflow不爲visible

關於overflow:visible:

overflow:visible的塊盒就不產生BFC,不但不產生BFC,啥FC都不產生,它的子元素直接搞進本身外層的BFC鳥::
overflow:visible這個限制只對所謂的塊盒(既包含塊級盒、本身又是塊級盒)存在,有些盒內部也能包含塊級元素,可是它自己又不是塊級元素(好比display爲table-cell、inline-block、或者盒自己是flex item等),由於外面不是BFC,因此它們不論如何必定會給包含的塊級盒建立一個新的BFC出來。

關於浮動:

浮動是個行級的行爲,當遇到浮動元素的時候,會首先"僞裝"它是個行內元素進行排版,排好後就往浮動的方向擠到擠不過去爲止(遇到邊界或者其它浮動元素)。
某一方向有clear的時候,浮動元素老是擠到邊界,在垂直方向上的行爲相似"換行"。
排好一個浮動元素以後,這一行就要重排一次。因此說浮動元素會形成行級的reflow。重排的時候,行盒會躲開浮動元素。以後的塊級盒(不管是行盒仍是其它盒)也都會躲開浮動元素排布。

三.BFC的做用及原理

1.自適應的兩欄佈局

代碼:

<style>
    body {
        width: 300px;
        position: relative;
    }
    .aside {
        width: 100px;
        height: 150px;
        float: left;
        background: #f66;
    }
    .main {
        height: 200px;
        background: #fcc;
    }
</style>
<body>
    <div class="aside"></div>
    <div class="main"></div>
</body>

頁面:
圖片描述

根據BFC佈局規則第3條:

每一個元素的margin-box的左邊, 與包含塊border-box的左邊相接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此。

所以,雖然存在浮動的元素aslide,但main的左邊依然會與包含塊的左邊相接觸。

根據BFC佈局規則第四條:

BFC的區域不會與float box重疊。

咱們能夠經過經過觸發main生成BFC, 來實現自適應兩欄佈局。

.main {
    overflow: hidden;
}

當觸發main生成BFC後,這個新的BFC不會與浮動的aside重疊。所以會根據包含塊的寬度,和aside的寬度,自動變窄。效果以下:

頁面:
圖片描述

對比: 實現佈局的另外一種方式利用塊狀元素流體特性實現的自適應佈局

利用塊狀元素流體特性實現的自適應佈局

經常使用方法:浮動或者定位+margin撐開

不足之處:咱們須要知道浮動或絕對定位內容的尺寸。而後,流體內容纔能有對應的margin或padding或border值進行位置修正。

2.清除內部浮動

代碼:

<style>
    .par {
        border: 5px solid #fcc;
        width: 300px;
    }
 
    .child {
        border: 5px solid #f66;
        width:100px;
        height: 100px;
        float: left;
    }
</style>
<body>
    <div class="par">
        <div class="child"></div>
        <div class="child"></div>
    </div>
</body>

頁面:
圖片描述

根據BFC佈局規則第六條:

計算BFC的高度時,浮動元素也參與計算

爲達到清除內部浮動,咱們能夠觸發par生成BFC,那麼par在計算高度時,par內部的浮動元素child也會參與計算。

.par {
    overflow: hidden;
}

效果以下:
圖片描述

3.防止margin重疊

代碼:

<style>
    p {
        color: #f55;
        background: #fcc;
        width: 200px;
        line-height: 100px;
        text-align:center;
        margin: 100px;
    }
</style>
<body>
    <p>Haha</p>
    <p>Hehe</p>
</body>

頁面:
圖片描述
兩個p之間的距離爲100px,發送了margin重疊。

根據BFC佈局規則第二條:

Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊

咱們能夠在p外面包裹一層容器,並觸發該容器生成一個BFC。那麼兩個P便不屬於同一個BFC,就不會發生margin重疊了。

代碼:

<style>
    .wrap {
        overflow: hidden;
    }
    p {
        color: #f55;
        background: #fcc;
        width: 200px;
        line-height: 100px;
        text-align:center;
        margin: 100px;
    }
</style>
<body>
    <p>Haha</p>
    <div class="wrap">
        <p>Hehe</p>
    </div>
</body>

效果以下:
圖片描述

4.總結

以上的幾個例子都體現了BFC佈局規則第五條:

BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素。反之也如此。

由於BFC內部的元素和外部的元素絕對不會互相影響,所以, 當BFC外部存在浮動時,它不該該影響BFC內部Box的佈局,BFC會經過變窄,而不與浮動有重疊。一樣的,當BFC內部有浮動時,爲了避免影響外部元素的佈局,BFC計算高度時會包括浮動的高度。避免margin重疊也是這樣的一個道理。

參考

1.前端精選文摘:BFC 神奇背後的原理
2.CSS之BFC詳解
3.BFC 、IFC
4.CSS深刻理解流體特性和BFC特性下多欄自適應佈局
5.CSS佈局

相關文章
相關標籤/搜索