CSS任何的排版都是有原因的,都是可以解釋的,這篇文章主要是介紹關于BFC的概念,内容循序漸進,希望能被了解和接受
1. 對CSS有了解的道友們肯定都知道盒式模型這個概念,對一個元素設定CSS,首先需要知道這個元素是block還是inline類型,但是無論這個元素是什麼類型,但是它們都是BOX概念的展現,關于CSS中BOX的概念: Box是CSS布局的基本機關: Box 是 CSS 布局的對象和基本機關, 直覺點來說,就是一個頁面是由很多個 Box 組成的,元素的類型和 display 屬性,決定了這個 Box 的類型, 不同類型的 Box, 會參與不同的 Formatting Context(一個決定如何渲染文檔的容器),是以Box内的元素會以不同的方式渲染。讓我們看看有哪些盒子: a)block-level box:display 屬性為 block, list-item, table 的元素,會生成 block-level box。并且參與 block fomatting context;
b)inline-level box:display 屬性為 inline, inline-block, inline-table 的元素,會生成 inline-level box。并且參與 inline formatting context;
PS: 頁面中的html标簽被浏覽器解析後,生成的元素将被添加到document tree中,但是CSS作用的對象并不是document tree, 而是根據document tree 生成的render tree,而盒子模型就是render tree的節點, 是以需要注意的有: 1 CSS作用的是盒子(BOX),而不是元素(Element) 2 JS無法直接操作盒子 3 行級盒子模型和塊級盒子模型結構一緻,隻是行級盒子模型在此基礎上有自身特性而已。 4. 對于盒子的組成而言,有四個部分,分别為content box, padding box, border box, margin box
2. 了解了上面的基礎知識後,就可以學習什麼是 Formatting Context Formatting Context: 頁面中的一個渲染區域,并且該區域擁有一套渲染規則,這套渲染規則決定了其子元素如何定位,以及與其他元素的互相關系和作用。 (CSS2.1 中隻有 BFC 和 IFC, CSS3 中還增加了 GFC 和 FFC) 簡單來說,FC就是頁面上的一塊渲染區域, 最常見的 Formatting context 有 Block fomatting context (BFC)和 Inline formatting context (IFC)
1) BFC(Block formatting context) : "塊級格式化上下文"。它是一個獨立的渲染區域,隻有block-level box參與, 它規定了内部的block-level box如何布局,并且與這個區域外部毫不相幹。
2) 如何讓一塊區域具有BFC的渲染規則:既然上文提到BFC是一塊渲染區域,那這塊渲染區域到底在哪,它又是有多大,這些由生成BFC的元素決定,CSS2.1中規定滿足下列CSS聲明之一的元素便會生成BFC。
(1)根元素(html、body)
(2)float的值不為none(left, right)
(3)overflow的值不為visible(hidden, scroll, inherit, auto..)
(4)display的值為inline-block、table-cell、table-caption
(5)position的值為absolute或fixed
具體的,BFC的限制規則如下面的描述(浏覽器對于BFC這塊區域的限制規則如下):
(1)能滿足條件形成BFC渲染區域元素的子元素(block-level box)會一個接一個的放置。垂直方向上他們的起點是一個包含塊的頂部(一個矩形),兩個相鄰子元素之間的垂直距離取決于元素的margin特性。在BFC中相鄰的塊級元素外邊距會折疊。
(2)能滿足生成BFC元素的子元素中,每一個子元素的外邊距與包含塊的左邊界相接觸,(對于從右到左的格式化,右外邊距接觸右邊界),即使浮動元素也是如此(盡管子元素的内容區域會由于浮動而壓縮),除非這個子元素也建立了一個新的BFC(如它自身也是一個浮動元素)。
上面的描述具有高度的抽象性,不是很容易了解,将它拆分如下成更加細緻化的BFC布局規則(切記下面布局的基礎是block-level box):
a)具有BFC渲染區域的元素内部的Box(block level)會在垂直方向,一個接一個地放置。
b)具有BFC渲染區域的元素内部的Box垂直方向的距離由margin決定。屬于同一個BFC的兩個相鄰Box的margin會發生重疊
c)每個子元素(具有BFC渲染區域的元素内部的子元素)的margin box的左邊,與包含塊border box的左邊相接觸(對于從左往右的格式化,否則相反)。即使存在浮動也是如此。
d)BFC的區域不會與float box重疊(這個特性的前提條件是對同一層級的BFC渲染區域和浮動元素對應生成的BFC渲染區域)。
e)BFC就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面的元素(我們往往利用這個特性來消除浮動元素對其非浮動的兄弟元素和其子元素帶來的影響。)。反之也如此。
f)計算BFC的高度時,浮動元素也參與計算(這個特性的前提條件是對父級的BFC渲染區域和子浮動元素對應生成的BFC渲染區域在計算父元素高度時,需要包含子浮動元素的高度才可以,這樣才能避免影響到該BFC外部區域)
上面的幾個就是細緻的BFC布局規則的拆分,可以嘗試和下面的一些常用的布局規則對照一下來體會:
Block元素會擴充到與父元素同寬,是以block元素會垂直排列
垂直方向上的兩個相鄰DIV的margin會重疊,而水準方向不會(此規則并不完全正确)
浮動元素會盡量接近往左上方(或右上方)
為父元素設定overflow:hidden或浮動父元素,則會包含浮動元素 ...........................
3. margin collapse,上面提到了一個外邊距合并的問題,這就是所謂的margin collapse, 具體的細節如下: 1. 合并外邊距與BFC:在CSS當中,相鄰的兩個盒子(可能是兄弟關系也可能是祖先關系)的外邊距可以結合成一個單獨的外邊距。這種合并外邊距的方式被稱為折疊,并且因而所結合成的外邊距稱為折疊外邊距。 2. 折疊的結果: 兩個相鄰的外邊距都是正數時,折疊結果是它們兩者之間較大的值。
兩個相鄰的外邊距都是負數時,折疊結果是兩者絕對值的較大值。
兩個外邊距一正一負時,折疊結果是兩者的相加的和。
3. 産生折疊的必備條件:margin必須是鄰接的!而根據w3c規範,兩個margin是鄰接的必須滿足以下條件:
(所謂的折疊的前提是在具有BFC渲染區域的内部的block-level Box)
(1)必須是處于正常文檔流(非float和絕對定位)的塊級盒子,并且處于同一個BFC當中。
(2)沒有線盒,沒有空隙(clearance,下面會講到),沒有padding和border将他們分隔開
(3)都屬于垂直方向上相鄰的外邊距,可以是下面任意一種情況
a) 元素的margin-top與其第一個正常文檔流的子元素的margin-top(子父關系,也即是具有BFC的盒子和内部的第一個block-level Box)
b) 元素的margin-bottom與其下一個正常文檔流的兄弟元素的margin-top(兄弟關系BFC盒子内部的block-level box之間)
c) height為auto的元素的margin-bottom與其最後一個正常文檔流的子元素的margin-bottom(子父關系,也即是具有BFC的盒子和内部的第一個block-level Box)
d) 高度為0并且最小高度也為0,不包含正常文檔流的子元素,并且自身沒有建立新的BFC的元素的margin-top和margin-bottom
4. 以上的條件意味着下列的規則:
建立了新的BFC的元素(例如浮動元素或者'overflow'值為'visible'以外的元素)與它的子元素的外邊距不會折疊
浮動元素不與任何元素的外邊距産生折疊(包括其父元素和子元素)
絕對定位元素不與任何元素的外邊距産生折疊
inline-block元素不與任何元素的外邊距産生折疊
一個正常文檔流元素的margin-bottom與它下一個正常文檔流的兄弟元素的margin-top會産生折疊,除非它們之間存在間隙(clearance)。
一個正常文檔流元素的margin-top 與其第一個正常文檔流的子元素的margin-top産生折疊,條件為父元素不包含 padding 和 border ,子元素不包含 clearance。
一個 'height' 為 'auto' 并且 'min-height' 為 '0'的正常文檔流元素的 margin-bottom 會與其最後一個正常文檔流子元素的 margin-bottom 折疊,條件為父元素不包含 padding 和 border ,子元素的 margin-bottom 不與包含 clearance 的 margin-top 折疊。
一個不包含border-top、border-bottom、padding-top、padding-bottom的正常文檔流元素,并且其 'height' 為 0 或 'auto', 'min-height' 為 '0',其裡面也不包含行盒(line box),其自身的 margin-top 和 margin-bottom 會折疊。
