BFC
-
box,Formatting Context
在解釋 BFC 是什么之前,需要先介紹 Box、Formatting Context的概念。
-
Box: CSS布局的基本單位
Box 是 CSS 布局的對象和基本單位, 直觀點來說,就是一個頁面是由很多個 Box 組成的。元素的類型和 display 屬性,決定了這個 Box 的類型。 不同類型的 Box, 會參與不同的 Formatting Context(一個決定如何渲染文檔的容器),因此Box內的元素會以不同的方式渲染。讓我們看看有哪些盒子:
- 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;
- run-in box: css3 中才有, 這兒先不講了。
-
Formatting context
Formatting context 是 W3C CSS2.1 規范中的一個概念。它是頁面中的一塊渲染區域,并且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關系和相互作用。最常見的 Formatting context 有 Block fomatting context (簡稱BFC)和 Inline formatting context (簡稱IFC)。
CSS2.1 中只有 BFC 和 IFC, CSS3 中還增加了 GFC 和 FFC。
-
什么是BFC
在一個Web頁面的CSS渲染中,塊級格式化上下文 (Block Fromatting Context)是按照塊級盒子布局的。W3C對BFC的定義如下:浮動元素和絕對定位元素,非塊級盒子的塊級容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不為“visiable”的塊級盒子,都會為他們的內容創建新的BFC(塊級格式上下文)。
為了便于理解,我們換一種方式來重新定義BFC。一個HTML元素要創建BFC,則滿足下列的任意一個或多個條件即可:1、float的值不是none。
2、position的值不是static或者relative。
3、display的值是inline-block、table-cell、flex、table-caption或者inline-flex
4、overflow的值不是visible
BFC是一個獨立的布局環境,其中的元素布局是不受外界的影響,并且在一個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垂直排列。
在行內格式化上下文中,框(boxes)一個接一個地水平排列,起點是包含塊的頂部。水平方向上的 margin,border 和 padding在框之間得到保留。框在垂直方向上可以以不同的方式對齊:它們的頂部或底部對齊,或根據其中文字的基線對齊。包含那些框的長方形區域,會形成一行,叫做行框。那么IFC一般有什么用呢?
水平居中:當一個塊要在環境中水平居中時,設置其為inline-block則會在外層產生IFC,通過text-align則可以使其水平居中。
垂直居中:創建一個IFC,用其中一個元素撐開父元素的高度,然后設置其vertical-align:middle,其他行內元素則可以在此父元素下垂直居中。
.container{ background: grey; text-align: center; height: 400px; width: 800px; display: table-cell; vertical-align: middle; } .column { width: 200px; height: 50px; background-color: green; display: inline-block; }
BFC布局規則:
- 內部的Box會在垂直方向,一個接一個地放置。
- Box垂直方向的距離由margin決定。屬于同一個BFC的兩個相鄰Box的margin會發生重疊
- 每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對于從左往右的格式化,否則相反)。即使存在浮動也是如此。
- BFC的區域不會與float box重疊。
- BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。反之也如此。
- 計算BFC的高度時,浮動元素也參與計算
-
怎么創建BFC
要顯示的創建一個BFC是非常簡單的,只要滿足上述4個CSS條件之一就行。例如:
<div class="container"> 你的內容 </div>
在類container中添加類似 overflow: scroll,overflow: hidden,display: flex,float: left,或 display: table 的規則來顯示創建BFC。雖然添加上述的任意一條都能創建BFC,但會有一些副作用:
1、display: table 可能引發響應性問題
2、overflow: scroll 可能產生多余的滾動條
3、float: left 將把元素移至左側,并被其他元素環繞
4、overflow: hidden 將裁切溢出元素因而無論什么時候需要創建BFC,都要基于自身的需要來考慮。對于本文,將采用 overflow: hidden 方式:
.container { overflow: hidden; }
-
BFC可以做什么呢?
-
利用BFC避免外邊距折疊
BFC可能造成外邊距折疊,也可以利用它來避免這種情況。BFC產生外邊距折疊要滿足一個條件:兩個相鄰元素要處于同一個BFC中。所以,若兩個相鄰元素在不同的BFC中,就能避免外邊距折疊。
<head> <meta charset="UTF-8"> <title>bfc</title> <style> body,ul,p,li{ margin: 0; padding: 0; } .container{ width: 800px; height: 700px; background: grey; float: left; } .container p{ width: 200px; height: 100px; margin: 50px; background: yellow; } .p3_container{ overflow: hidden; } </style> </head> <body> <div class="container"> <p>p1</p> <p>p2</p> <div class="p3_container"> <p>p3</p> </div> </div> </body>
BFC包含浮動(解決高度塌陷)(計算BFC的高度時,浮動元素也參與計算)
浮動元素是會脫離文檔流的(絕對定位元素會脫離文檔流)。如果一個沒有高度或者height是auto的容器的子元素是浮動元素,則該容器的高度是不會被撐開的。我們通常會利用偽元素(:after或者:before)來解決這個問題。BFC能包含浮動,也能解決容器高度不會被撐開的問題。-
使用BFC避免文字環繞(BFC的區域不會與float box重疊)
對于浮動元素,可能會造成文字環繞的情況(Figure1),但這并不是我們想要的布局(Figure2才是想要的)。要解決這個問題,我們可以用外邊距,但也可以用BFC。
.container{ width: 800px; height: 700px; background: grey; float: left; } <div class="container"> <div class="img-container"><img src="../images/square-02.png" alt=""></div> <p> First let us understand why the text wraps. For this we have to understand how the box model works when an element is floated. This is the part I left earlier while discussing the alignment in a block formatting context. Let us understand what is happening in Figure 1 in the diagram below: </p> </div>
造成文字環繞的原因
在BFC上下文中,每個盒子的左外側緊貼包含塊的左側(從右到左的格式里,則為盒子右外側緊貼包含塊右側),甚至有浮動也是如此(盡管盒子里的行盒子 Line Box 可能由于浮動而變窄),除非盒子創建了一個新的BFC(在這種情況下盒子本身可能由于浮動而變窄)。
因而,如果p元素創建一個新的BFC那它就不會再緊貼包含塊的左側了。 -
在多列布局中使用BFC
如果我們創建一個占滿整個容器寬度的多列布局,在某些瀏覽器中最后一列有時候會掉到下一行。這可能是因為瀏覽器四舍五入了列寬從而所有列的總寬度會超出容器。但如果我們在多列布局中的最后一列里創建一個新的BFC,它將總是占據其他列先占位完畢后剩下的空間。
例如: <div class="container"> <div class="column">column 1</div> <div class="column">column 2</div> <div class="column">column 3</div> </div> 對應的CSS: .column { width: 31.33%; background-color: green; float: left; margin: 0 1%; } /* Establishing a new block formatting context in the last column */ .column:last-child { float: none; overflow: hidden; }
-