歡迎光臨
每天分享高質量文章

學習BFC

作者:elcarim的部落格

網址:http://www.cnblogs.com/elcarim5efil/p/4745796.html

BFC全稱是Block Formatting Context,即塊格式化背景關係。它是CSS2.1規範定義的,關於CSS渲染定位的一個概念。要明白BFC到底是什麼,首先來看看什麼是視覺格式化模型。

視覺格式化模型

視覺格式化模型(visual formatting model)是用來處理檔案並將它顯示在視覺媒體上的機制,它也是CSS中的一個概念。

視覺格式化模型定義了盒(Box)的生成,盒主要包括了塊盒、行內盒、匿名盒(沒有名字不能被選擇器選中的盒)以及一些實驗性的盒(未來可能新增到規範中)。盒的型別由display屬性決定。

塊盒(block box)

塊盒有以下特性:

  • 當元素的CSS屬性display為block,list-item或 table時,它是塊級元素 block-level;
  • 視覺上呈現為塊,豎直排列;
  • 塊級盒參與(塊格式化背景關係);
  • 每個塊級元素至少生成一個塊級盒,稱為主要塊級盒(principal block-level box)。一些元素,比如
  • ,生成額外的盒來放置專案符號,不過多數元素只生成一個主要塊級盒。

行內盒(inline box)

  • 當元素的CSS屬性display的計算值為inline,inline-block或inline-table時,稱它為行內級元素;
  • 視覺上它將內容與其它行內級元素排列為多行;典型的如段落內容,有文字(可以有多種格式譬如著重),或圖片,都是行內級元素;
  • 行內級元素生成行內級盒(inline-level boxes),參與行內格式化背景關係(inline formatting context)。同時參與生成行內格式化背景關係的行內級盒稱為行內盒(inline boxes)。所有display:inline的非替換元素生成的盒是行內盒;
  • 不參與生成行內格式化背景關係的行內級盒稱為原子行內級盒(atomic inline-level boxes)。這些盒由可替換行內元素,或 display 值為 inline-block 或inline-table 的元素生成,不能拆分成多個盒;

匿名盒(anonymous box)

匿名盒也有份匿名塊盒與匿名行內盒,因為匿名盒沒有名字,不能利用選擇器來選擇它們,所以它們的所有屬性都為inherit或初始預設值;

如下麵例子,會創鍵匿名塊盒來包含毗鄰的行內級盒:

Some inline text

followed by a paragraph

followed by more inline text.

三個定位方案

在定位的時候,瀏覽器就會根據元素的盒型別和背景關係對這些元素進行定位,可以說盒就是定位的基本單位。定位時,有三種定位方案,分別是常規流,浮動已經絕對定位。

常規流(Normal flow)

  • 在常規流中,盒一個接著一個排列;
  • 在塊級格式化背景關係裡面, 它們豎著排列;
  • 在行內格式化背景關係裡面, 它們橫著排列;
  • 當position為static或relative,並且float為none時會觸發常規流;
  • 對於靜態定位(static positioning),position: static,盒的位置是常規流佈局裡的位置;
  • 對於相對定位(relative positioning),position: relative,盒偏移位置由這些屬性定義top,bottom,leftandright。即使有偏移,仍然保留原有的位置,其它常規流不能佔用這個位置。

浮動(Floats)

  • 盒稱為浮動盒(floating boxes);
  • 它位於當前行的開頭或末尾;
  • 這導致常規流環繞在它的周邊,除非設定 clear 屬性;

絕對定位(Absolute positioning)


  • 絕對定位方案,盒從常規流中被移除,不影響常規流的佈局;
  • 它的定位相對於它的包含塊,相關CSS屬性:top,bottom,left及right;
  • 如果元素的屬性position為absolute或fixed,它是絕對定位元素;
  • 對於position: absolute,元素定位將相對於最近的一個relative、fixed或absolute的父元素,如果沒有則相對於body;

塊格式化背景關係

到這裡,已經對CSS的定位有一定的瞭解了,從上面的資訊中也可以得知,塊格式背景關係是頁面CSS 視覺渲染的一部分,用於決定塊盒子的佈局及浮動相互影響範圍的一個區域。

BFC的建立方法

  • 根元素或其它包含它的元素;
  • 浮動 (元素的float不為none);
  • 絕對定位元素 (元素的position為absolute或fixed);
  • 行內塊inline-blocks(元素的 display: inline-block);
  • 表格單元格(元素的display: table-cell,HTML表格單元格預設屬性);
  • overflow的值不為visible的元素;
  • 彈性盒 flex boxes (元素的display: flex或inline-flex);

但其中,最常見的就是overflow:hidden、float:left/right、position:absolute。也就是說,每次看到這些屬性的時候,就代表了該元素以及建立了一個BFC了。

BFC的範圍

BFC的範圍在MDN中是這樣描述的。

A block formatting context contains everything inside of the element creating it that is not also inside a descendant element that creates a new block formatting context.

中文的意思一個BFC包含建立該背景關係元素的所有子元素,但不包括建立了新BFC的子元素的內部元素。

這段看上去有點奇怪,我是這麼理解的,加入有下麵程式碼,class名為.BFC代表建立了新的塊格式化:

這段程式碼表示,#div_1建立了一個塊格式背景關係,這個背景關係包括了#div_2、#div_3、#div_4、#div_5。即#div_2中的子元素也屬於#div_1所建立的BFC。但由於#div_5建立了新的BFC,所以#div_6和#div_7就被排除在外層的BFC之外。

我認為,這從另一方角度說明,一個元素不能同時存在於兩個BFC中。

BFC的一個最重要的效果是,讓處於BFC內部的元素與外部的元素相互隔離,使內外元素的定位不會相互影響。這是利用BFC清除浮動所利用的特性,關於清除浮動將在後面講述。

如果一個元素能夠同時處於兩個BFC中,那麼就意味著這個元素能與兩個BFC中的元素發生作用,就違反了BFC的隔離作用,所以這個假設就不成立了。

BFC的效果

就如剛才提到的,BFC的最顯著的效果就是建立一個隔離的空間,斷絕空間內外元素間相互的作用。然而,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).

簡單歸納一下:

  1. 內部的盒會在垂直方向一個接一個排列(可以看作BFC中有一個的常規流);
  2. 處於同一個BFC中的元素相互影響,可能會發生margin collapse;
  3. 每個元素的margin box的左邊,與容器塊border box的左邊相接觸(對於從左往右的格式化,否則相反)。即使存在浮動也是如此;
  4. BFC就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面的元素,反之亦然;
  5. 計算BFC的高度時,考慮BFC所包含的所有元素,連浮動元素也參與計算;
  6. 浮動盒區域不疊加到BFC上;

這麼多性質有點難以理解,但可以作如下推理來幫助理解:html的根元素就是,而根元素會建立一個BFC,建立一個新的BFC時就相當於在這個元素內部建立一個新的,子元素的定位就如同在一個新頁面中那樣,而這個新舊html頁面之間時不會相互影響的。

上述這個理解並不是最準確的理解,甚至是將因果倒置了(因為html是根元素,因此才會有BFC的特性,而不是BFC有html的特性),但這樣的推理可以幫助理解BFC這個概念。

從實際程式碼來分析BFC

講了這麼多,還是比較難理解,所以下麵透過一些例子來加深對BFC的認識。

實體一


贊(0)

分享創造快樂