在上文《詳說清除浮動》中,Kayo 較爲詳細地介紹了 BFC ,也就是本文的主角 Block Formatting Contexts (塊級格式化上下文),本文會基於上文關於 BFC 的部分進行拓展,進一步說明 BFC 的特性。html

但在進一步說明 BFC 特性以前,Kayo 首先要介紹另外一個在 CSS 的可視化格式模型 (Visual Formatting Model) 中具備很是重要地位的概念——定位方案。定位方案是控制元素的佈局,在 CSS 2.1 中,有三種定位方案——普通流 (Normal Flow) 、浮動 (Floats) 和絕對定位 (Absolute Positioning) ,下面分別對這三種佈局簡略說明一下。瀏覽器

普通流(Normal Flow)ide

在普通流中,元素按照其在 HTML 中的前後位置至上而下佈局,在這個過程當中,行內元素水平排列,直到當行被佔滿而後換行,塊級元素則會被渲染爲完整的一個新行, 除非另外指定,不然全部元素默認都是普通流定位,也能夠說,普通流中元素的位置由該元素在 HTML 文檔中的位置決定。佈局

浮動 (Floats)post

在浮動佈局中,元素首先按照普通流的位置出現,而後根據浮動的方向儘量的向左邊或右邊偏移,其效果與印刷排版中的文本環繞類似。google

絕對定位 (Absolute Positioning)orm

在絕對定位佈局中,元素會總體脫離普通流,所以絕對定位元素不會對其兄弟元素形成影響(若是看了上文的童鞋,會發現這點與浮動元素會影響兄弟元素是不一樣的),而元素具體的位置由絕對定位的座標決定。htm

BFC 正是屬於普通流的,所以它對兄弟元素也不會形成什麼影響。開發

一. BFC 是什麼?

有了上面的基礎後,能夠正式介紹 BFC 了。從樣式上看,具備 BFC 的元素與普通的容器沒有什麼區別,可是從功能上,具備 BFC 的元素能夠看做是隔離了的獨立容器,容器裏面的元素不會在佈局上影響到外面的元素,而且 BFC 具備普通容器沒有的一些特性,例如能夠包含浮動元素,上文中的第二類清除浮動的方法(如 overflow 方法)就是觸發了浮動元素的父元素的 BFC ,使到它能夠包含浮動元素,從而防止出現高度塌陷的問題。rem

簡單來講,BFC 就是一種屬性,這種屬性會影響着元素的定位以及與其兄弟元素之間的相互做用。

二.如何觸發 BFC

上面介紹了 BFC 的定義,那麼如何觸發 BFC 呢?

知足下面任一條件的元素,會觸發爲 BFC :

  • 浮動元素,float 除 none 之外的值
  • 絕對定位元素,position(absolute,fixed)
  • display 爲如下其中之一的值 inline-blocks,table-cells,table-captions
  • overflow 除了 visible 之外的值(hidden,auto,scroll)

可是,"display:table" 自己並不產生 BFC,而是由它產生匿名框,匿名框中包含 "display:table-cell" 的框會產 BFC。 總之,對於 "display:table" 的元素,產生 BFC 的是匿名框而不是 "display:table"。

在 CSS3 中,BFC 叫作 Flow Root,並增長了一些觸發條件:

  • display 的 table-caption 值
  • position 的 fixed 值,其實 fixed 是 absolute 的一個子類,所以在 CSS2.1 中使用這個值也會觸發 BFC ,只是在 CSS3 中更加明確了這一點。

值得注意的是,在前面 Kayo 已經說明過了,BFC 並非元素,而是某些元素帶有的一些屬性,所以,是上面這些元素產生了 BFC ,而它們自己並非 BFC ,這個概念須要區分清楚。

三. BFC 的特性

從總體上看,BFC 是隔離了的容器,這個具體能夠表現爲三個特性:

1. BFC 會阻止外邊距摺疊

兩個相連的 div 在垂直上的外邊距會發生疊加,有些書籍會把這個狀況列做 bug ,這裏 Kayo 並不一樣意,這種摺疊雖然會給不熟悉 CSS 佈局的開發者帶來一些不便,但實際上它具備完整且具體的摺疊規則,而且在主流瀏覽器中都存在,所以 Kayo 更認爲這應該是 CSS 的特性。固然,在實際開發中,或許咱們有時會不須要這種摺疊,這時能夠利用 BFC 的其中一個特性——阻止外邊距疊加。

在舉例說明 BFC 如何阻止外邊距摺疊以前,首先說明一下外邊距摺疊的規則:僅當兩個塊級元素相鄰而且在同一個塊級格式化上下文時,它們垂直方向之間的外邊距纔會疊加。也就是說,即使兩個塊級元素相鄰,但當它們不在同一個塊級格式化上下文時它們的邊距也不會摺疊。所以,阻止外邊距摺疊只需產生新的 BFC 。

效果如圖:

也能夠看 Demo 。

如上圖的例子,三個 div 各包含一個 p 元素,三個 div 及其包含的 p 元素都有頂部和底部的外邊距,但只有第三個 div 的邊距沒有與它的子元素 p 的外邊距摺疊。這是由於第三個 div 建立了新的 BFC ,因而可知:建立了 BFC 的元素,不和它的子元素髮生外邊距摺疊。

2. BFC 能夠包含浮動的元素

這也正是使用 overflow: hidden 與 overflow: auto 方法閉合浮動的原理,使用 overflow: hidden 或 overflow: auto 觸發浮動元素的父元素的 BFC 特性,從而能夠包含浮動元素,閉合浮動。

W3C 的原文是「'Auto' heights for block formatting context roots」,也就是 BFC 會根據子元素的狀況自動適應高度,即便其子元素中包括浮動元素。

效果如圖:

也能夠看 Demo 。

上面的例子中,有兩個 div ,它們各包含一個設置了浮動的 p 元素,但第一個 div 出現了「高度塌陷」,這是由於內部的浮動元素脫離了普通流,所以該 div 至關於一個空標籤,沒有高度和寬度,即高度爲 0 ,上下邊框也重疊在一塊兒。而第二個 div 使用 overflow: hidden 觸發了 BFC ,能夠包含浮動元素,所以能正確表現出高度,其邊框位置也正常了。

3. BFC 能夠阻止元素被浮動元素覆蓋

如上文所說,浮動元素的塊級兄弟元素會無視浮動元素的位置,儘可能佔滿一整行,這樣就會被浮動元素覆蓋,爲該兄弟元素觸發 BFC 後能夠阻止這種狀況的發生。

效果如圖:

也能夠看 Demo 。

如上圖的例子,藍色背景的 div 使用 overflow: hidden 觸發了 BFC ,它並不會被它的兄弟浮動元素覆蓋,而是處於它的旁邊。值得注意的是,以上的狀況僅僅是元素寬度之和沒有超出父元素寬度的狀況,假設浮動元素寬度和它的非浮動兄弟元素寬度都沒有超過父元素寬度,但兩個元素的寬度加起來超出了父元素寬度的時候,非浮動元素會降低到下一行,即處於浮動元素下方,效果以下圖:

也能夠看 Demo 。

四. BFC 與 hasLayout

細心的童鞋會發現,在上面的例子中,除了使用 overflow: hidden 觸發 BFC 外,還使用了一個 *zomm: 1 的屬性,這是 IEhack ,由於 IE6-7 並不支持 W3C 的 BFC ,而是使用私有屬性 hasLayout 。從表現上來講,hasLayout 跟 BFC 很類似,只是 hasLayout 自身存在不少問題,致使了 IE6-7 中一系列的 bug 。觸發 hasLayout 的條件與觸發 BFC 有些類似,具體狀況 Kayo 會另寫文章介紹。這裏 Kayo 推薦爲元素設置 IE 特有的 CSS 屬性 zoom: 1 觸發 hasLayout ,zoom 用於設置或檢索元素的縮放比例,值爲「1」即便用元素的實際尺寸,使用 zoom: 1 既能夠觸發 hasLayout 又不會對元素形成其餘影響,相對來講會更爲方便。

這時咱們須要注意一個問題:既然 hasLayout 有着跟 BFC 類似的功能,那麼在實際開發中,就要爲須要觸發 BFC 的元素同時觸發 hasLayout ,這樣 BFC 和 hasLayout 具備的一些特殊性質能夠在現代瀏覽器和 IE 中同時產生,避免一個元素在不一樣瀏覽器間的表現由於 BFC 或 hasLayout 出現差別。事實上,在實際開發中不少莫名其妙的問題其實都是所以而產生的。固然一樣地,若是一個元素沒有觸發 BFC ,也要儘可能保證它沒有觸發 hasLayout 。

本文由 Kayo Lee 發表,本文連接:http://kayosite.com/block-formatting-contexts-in-detail.html