前言
什么是BFC?
在解釋 BFC 是什么之前,需要先介紹Box(塊級,行級...)、FormattingContext的概念。
Box: CSS布局的基本單位&盒模型
盒模型--塊級盒/行內盒
一個盒包括了內容(content)、邊(border)、內邊距(padding)、外邊距(margin)。下圖展示了盒模型的直觀意義:
盒的尺寸(width與height--計算得到的offsetWidth和offsetHeight)定義受到box-sizing屬性的影響。box-sizing可選擇content-box(默認)和border-box兩種模式。分別代表兩種盒子模型:W3c標准盒模型和IE盒子模型。ie8后開始支持通過CSS3屬性box-sizing,讓我們可以自由選擇采用哪種盒子。
w3c標准盒模型--塊級盒
width = content-width + padding-width + border-width
height = content-height + padding-height + border-height
IE盒子模型--塊級盒
width = content-width
height = content-height
行內盒
1.width、height不起作用,盒子高度由內容決定(font-size/line-height)決定
2.margin-top/margin-bottom/padding-top/padding-bottom不起作用
小結
:
- 兩類塊級盒子可用過設置box-sizing轉換。
- 行內盒與塊級盒轉換可通過設置display屬性來修改。下文將具體說明那些屬性生成塊級盒,哪些生成行內盒
- 行內盒參與IFC布局,塊級盒參與BFC布局,如果塊級盒包含行內盒,但是由於BFC內只有塊級盒參與,因此行內盒會被匿名塊級盒包含。
BOX
Box 是 CSS 布局的對象和基本單位, 直觀點來說,就是一個頁面是由很多個 Box 組成的。元素的類型和 display 屬性,決定了這個 Box 的類型。 不同類型的 Box, 會參與不同的 Formatting Context(一個決定如何渲染文檔的容器),因此Box內的元素會以不同的方式渲染。讓我們看看有哪些盒子:
盒子 | 解釋 |
---|---|
block-level | box的display 屬性為block , list-item , table 的元素,會生成 block-level box 。並且參與(BFC)block fomatting context; |
inline-level | box的display 屬性為inline , inline-block , inline-table 的元素,會生成 inline-level box 。並且參與 inline formatting context; |
run-in box |
css3 中才有, 這兒先不講了。 |
格式化上下文
格式化上下文( formatting contexts )
├── 塊級格式化上下文( Block formatting contexts )( BFC )
├── 行內格式化上下文( Inline formatting contexts ) ( IFC )
├── 自適應格式化上下文( Flex Formatting Contexts )( FFC )
└── 網格布局格式化上下文( GridLayout Formatting Contexts )( GFC )
有一類盒被稱為塊容器,它們能夠包含塊級盒。塊容器要么創建BFC,這樣它內部僅僅包含塊級盒,要么創建一個IFC,這樣它內部僅僅包含行內級元素。(也就是說,塊容器中不可能既包含塊級盒,又包含行內級盒,一旦他的子盒中有塊級盒,所有行內級盒都會被自動創建匿名盒包裹)。
在非塊級格式化上下文中的塊容器總是會創建新的BFC:如display為inline-blocks, table-cells, 和table-captions所生成的盒。而自身也在塊級格式化上下文中的塊容器,則只有overflow不為visible的情形下才會創建新的BFC。
絕對定位和浮動的塊容器則總是會創建新的塊級格式化上下文。
display值為table或者inline-table的元素將會生成表格(table),表格內部會使用特殊的格式化方式來排布其內部元素。
display值為grid或者inline-grid的元素將會生成格元素(grid element),與table情形類似,它內部也是使用特殊的格式化方式來牌不其內部元素,
display值為flex或者inline-flex的元素將會生成自適應容器(flex container),自適應容器在其內部產生自適應格式化上下文(flex formatting context)
What's FC?
FC的全稱是:Formatting Contexts,是W3C CSS2.1規范中的一個概念。它是頁面中的一塊渲染區域,並且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關系和相互作用。
格式化上下文 | 定義 | 應用 |
---|---|---|
BFC | BFC(Block Formatting Contexts)直譯為"塊級格式化上下文"。Block Formatting Contexts就是頁面上的一個隔離的渲染區域,容器里面的子元素不會在布局上影響到外面的元素,反之也是如此。 | 如何產生BFC?float的值不為none。overflow的值不為visible。 position的值不為relative和static。display的值為table-cell, table-caption, inline-block中的任何一個。 那BFC一般有什么用呢?比如常見的多欄布局,結合塊級別元素浮動,里面的元素則是在一個相對隔離的環境里運行。 |
IFC | IFC(Inline Formatting Contexts)直譯為"內聯格式化上下文",IFC的line box(線框)高度由其包含行內元素中最高的實際高度計算而來(不受到豎直方向的padding/margin影響).IFC中的line box一般左右都貼緊整個IFC,但是會因為float元素而擾亂。float元素會位於IFC與與line box之間,使得line box寬度縮短。 同個ifc下的多個line box高度會不同。 IFC中時不可能有塊級元素的,當插入塊級元素時(如p中插入div)會產生兩個匿名塊與div分隔開,即產生兩個IFC,每個IFC對外表現為塊級元素,與div垂直排列。 | 那么IFC一般有什么用呢?水平居中:當一個塊要在環境中水平居中時,設置其為inline-block則會在外層產生IFC,通過text-align則可以使其水平居中。垂直居中:創建一個IFC,用其中一個元素撐開父元素的高度,然后設置其vertical-align:middle,其他行內元素則可以在此父元素下垂直居中。 |
GFC | GFC(GridLayout Formatting Contexts)直譯為"網格布局格式化上下文",當為一個元素設置display值為grid的時候,此元素將會獲得一個獨立的渲染區域,我們可以通過在網格容器(grid container)上定義網格定義行(grid definition rows)和網格定義列(grid definition columns)屬性各在網格項目(grid item)上定義網格行(grid row)和網格列(grid columns)為每一個網格項目(grid item)定義位置和空間。 | 那么GFC有什么用呢,和table又有什么區別呢?首先同樣是一個二維的表格,但GridLayout會有更加豐富的屬性來控制行列,控制對齊以及更為精細的渲染語義和控制。 |
FFC | FFC(Flex Formatting Contexts)直譯為"自適應格式化上下文",display值為flex或者inline-flex的元素將會生成自適應容器(flex container),可惜這個牛逼的屬性只有谷歌和火狐支持,不過在移動端也足夠了,至少safari和chrome還是OK的,畢竟這倆在移動端才是王道。 | Flex Box 由伸縮容器和伸縮項目組成。通過設置元素的 display 屬性為 flex 或 inline-flex 可以得到一個伸縮容器。設置為 flex 的容器被渲染為一個塊級元素,而設置為 inline-flex 的容器則渲染為一個行內元素。|伸縮容器中的每一個子元素都是一個伸縮項目。伸縮項目可以是任意數量的。伸縮容器外和伸縮項目內的一切元素都不受影響。簡單地說,Flexbox 定義了伸縮容器內伸縮項目該如何布局。 |
什么是BFC?(Block formatting contexts)
w3c規范定義:
浮動元素和絕對定位元素,非塊級盒子的塊級容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不為“visiable”的塊級盒子,都會為他們的內容創建新的BFC(塊級格式上下文)。
BFC的通俗理解:
首先BFC是一個名詞,是一個獨立的布局環境,我們可以理解為一個箱子(實際上是看不見摸不着的),箱子里面物品的擺放是不受外界的影響的。轉換為BFC的理解則是:BFC中的元素的布局是不受外界的影響(我們往往利用這個特性來消除浮動元素對其非浮動的兄弟元素和其子元素帶來的影響。)並且在一個BFC中,塊盒與行盒(行盒由一行中所有的內聯元素所組成,並非指一個行內元素就產生一個行盒)都會垂直的沿着其父元素的邊框排列。
總的來說:
BFC(Block formatting context)直譯為"塊級格式化上下文"。它是一個獨立的渲染區域,只有Block-level box
參與, 它規定了內部的Block-level Box如何布局,並且與這個區域外部毫不相干。
BFC布局規則:
- 內部的Box會在垂直方向,一個接一個地放置。
- Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊
- 每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,否則相反)。即使存在浮動也是如此。
- BFC的區域不會與float box重疊。
- BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。反之也如此。
- 計算BFC的高度時,浮動元素也參與計算
那些元素生成BFC
- 根元素
- float屬性不為none
- position為absolute或fixed
- display為inline-block, table-cell, table-caption, flex, inline-flex
- overflow不為visible
元素與盒
在HTML中常常使用的概念是元素,而在CSS中,布局的基本單位是盒,盒總是矩形的。
元素與盒並非一一對應的關系,一個元素可能生成多個盒,CSS規則中的偽元素也可能生成盒,display屬性為none的元素則不生成盒。
除了元素之外,HTML中的文本節點也可能會生成盒。
正常流
正常流是頁面,大部分盒排布於正常流中。正常流中的盒必定位於某一格式化上下文中,正常流中有兩種格式化上下文:塊級格式化上下文(block formatting context,簡稱BFC)和行內格式化上下文(inline formatting context,IFC)。
在塊級格式化上下文中,盒呈縱向排布,在行內格式化上下文中,盒則呈橫向排布。
正常流根容器中是塊級格式化上下文,不同的盒可能會在內部產生行內格式化上下文或者塊級格式化上下文。
塊級與行內級
正常流中的盒分為塊級與行內級兩種,任何一個行內級盒都不能夠直接被放入塊級格式化上下文中。如果有一個HTML元素生成了一個行內盒,而其所在的上下文是塊級的話,那么應當為它生成一個匿名塊級盒,匿名塊級盒會在內部生成行內格式化上下文。
元素的display屬性會決定盒是行內級還是塊級:
- block, table, flex, grid, list-item 為塊級
- inline, inline-block, inline-table, inline-flex, inline-grid 為行內級
產生垂直外邊距合並的必備條件
兩個margin是鄰接的必須滿足以下條件:
- 必須是處於常規文檔流(非float和絕對定位)的塊級盒子,並且處於同一個BFC當中。
- 沒有線盒,沒有空隙(clearance,下面會講到),沒有padding和border將他們分隔開
- 都屬於垂直方向上相鄰的外邊距,可以是下面任意一種情況
- 元素的margin-top與其第一個常規文檔流的子元素的margin-top
- 元素的margin-bottom與其下一個常規文檔流的兄弟元素的margin-top
- height為auto的元素的margin-bottom與其最后一個常規文檔流的子元素的margin-bottom
- 高度為0並且最小高度也為0,不包含常規文檔流的子元素,並且自身沒有建立新的BFC的元素的margin-top和margin-bottom
最后來看張圖慢慢領會