BFC
-
box,Formatting Context
在解釋 BFC 是什么之前痪蝇,需要先介紹 Box、Formatting Context的概念本冲。
-
Box: CSS布局的基本單位
Box 是 CSS 布局的對(duì)象和基本單位讶隐, 直觀點(diǎn)來說鞍帝,就是一個(gè)頁(yè)面是由很多個(gè) Box 組成的。元素的類型和 display 屬性舷暮,決定了這個(gè) Box 的類型态罪。 不同類型的 Box, 會(huì)參與不同的 Formatting Context(一個(gè)決定如何渲染文檔的容器)下面,因此Box內(nèi)的元素會(huì)以不同的方式渲染复颈。讓我們看看有哪些盒子:
- block-level box:display 屬性為 block, list-item, table 的元素,會(huì)生成 block-level box沥割。并且參與 block fomatting context耗啦;
- inline-level box:display 屬性為 inline, inline-block, inline-table 的元素,會(huì)生成 inline-level box机杜。并且參與 inline formatting context帜讲;
- run-in box: css3 中才有, 這兒先不講了椒拗。
-
Formatting context
Formatting context 是 W3C CSS2.1 規(guī)范中的一個(gè)概念似将。它是頁(yè)面中的一塊渲染區(qū)域获黔,并且有一套渲染規(guī)則,它決定了其子元素將如何定位玩郊,以及和其他元素的關(guān)系和相互作用肢执。最常見的 Formatting context 有 Block fomatting context (簡(jiǎn)稱BFC)和 Inline formatting context (簡(jiǎn)稱IFC)。
CSS2.1 中只有 BFC 和 IFC, CSS3 中還增加了 GFC 和 FFC译红。
-
什么是BFC
在一個(gè)Web頁(yè)面的CSS渲染中预茄,塊級(jí)格式化上下文 (Block Fromatting Context)是按照塊級(jí)盒子布局的。W3C對(duì)BFC的定義如下:浮動(dòng)元素和絕對(duì)定位元素侦厚,非塊級(jí)盒子的塊級(jí)容器(例如 inline-blocks, table-cells, 和 table-captions)耻陕,以及overflow值不為“visiable”的塊級(jí)盒子,都會(huì)為他們的內(nèi)容創(chuàng)建新的BFC(塊級(jí)格式上下文)刨沦。
為了便于理解诗宣,我們換一種方式來重新定義BFC。一個(gè)HTML元素要?jiǎng)?chuàng)建BFC想诅,則滿足下列的任意一個(gè)或多個(gè)條件即可:1召庞、float的值不是none。
2来破、position的值不是static或者relative篮灼。
3、display的值是inline-block徘禁、table-cell诅诱、flex、table-caption或者inline-flex
4送朱、overflow的值不是visible
BFC是一個(gè)獨(dú)立的布局環(huán)境娘荡,其中的元素布局是不受外界的影響,并且在一個(gè)BFC中驶沼,塊盒與行盒(行盒由一行中所有的內(nèi)聯(lián)元素所組成)都會(huì)垂直的沿著其父元素的邊框排列炮沐。
IFC布局規(guī)則:
IFC(Inline Formatting Contexts)直譯為"內(nèi)聯(lián)格式化上下文",IFC的line box(線框)高度由其包含行內(nèi)元素中最高的實(shí)際高度計(jì)算而來(不受到豎直方向的padding/margin影響)IFC中的line box一般左右都貼緊整個(gè)IFC回怜,但是會(huì)因?yàn)閒loat元素而擾亂央拖。float元素會(huì)位于IFC與與line box之間,使得line box寬度縮短鹉戚。 同個(gè)ifc下的多個(gè)line box高度會(huì)不同鲜戒。 IFC中時(shí)不可能有塊級(jí)元素的,當(dāng)插入塊級(jí)元素時(shí)(如p中插入div)會(huì)產(chǎn)生兩個(gè)匿名塊與div分隔開抹凳,即產(chǎn)生兩個(gè)IFC遏餐,每個(gè)IFC對(duì)外表現(xiàn)為塊級(jí)元素,與div垂直排列赢底。
在行內(nèi)格式化上下文中失都,框(boxes)一個(gè)接一個(gè)地水平排列柏蘑,起點(diǎn)是包含塊的頂部。水平方向上的 margin粹庞,border 和 padding在框之間得到保留咳焚。框在垂直方向上可以以不同的方式對(duì)齊:它們的頂部或底部對(duì)齊庞溜,或根據(jù)其中文字的基線對(duì)齊革半。包含那些框的長(zhǎng)方形區(qū)域,會(huì)形成一行流码,叫做行框又官。那么IFC一般有什么用呢?
水平居中:當(dāng)一個(gè)塊要在環(huán)境中水平居中時(shí)漫试,設(shè)置其為inline-block則會(huì)在外層產(chǎn)生IFC六敬,通過text-align則可以使其水平居中。
垂直居中:創(chuàng)建一個(gè)IFC驾荣,用其中一個(gè)元素?fù)伍_父元素的高度外构,然后設(shè)置其vertical-align:middle,其他行內(nèi)元素則可以在此父元素下垂直居中播掷。
.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布局規(guī)則:
- 內(nèi)部的Box會(huì)在垂直方向审编,一個(gè)接一個(gè)地放置。
- Box垂直方向的距離由margin決定叮趴。屬于同一個(gè)BFC的兩個(gè)相鄰Box的margin會(huì)發(fā)生重疊
- 每個(gè)元素的margin box的左邊, 與包含塊border box的左邊相接觸(對(duì)于從左往右的格式化权烧,否則相反)眯亦。即使存在浮動(dòng)也是如此。
- BFC的區(qū)域不會(huì)與float box重疊般码。
- BFC就是頁(yè)面上的一個(gè)隔離的獨(dú)立容器妻率,容器里面的子元素不會(huì)影響到外面的元素。反之也如此板祝。
- 計(jì)算BFC的高度時(shí)宫静,浮動(dòng)元素也參與計(jì)算
-
怎么創(chuàng)建BFC
要顯示的創(chuàng)建一個(gè)BFC是非常簡(jiǎn)單的,只要滿足上述4個(gè)CSS條件之一就行券时。例如:
<div class="container"> 你的內(nèi)容 </div>
在類container中添加類似 overflow: scroll孤里,overflow: hidden,display: flex橘洞,float: left捌袜,或 display: table 的規(guī)則來顯示創(chuàng)建BFC。雖然添加上述的任意一條都能創(chuàng)建BFC炸枣,但會(huì)有一些副作用:
1虏等、display: table 可能引發(fā)響應(yīng)性問題
2弄唧、overflow: scroll 可能產(chǎn)生多余的滾動(dòng)條
3、float: left 將把元素移至左側(cè)霍衫,并被其他元素環(huán)繞
4候引、overflow: hidden 將裁切溢出元素因而無論什么時(shí)候需要?jiǎng)?chuàng)建BFC,都要基于自身的需要來考慮敦跌。對(duì)于本文澄干,將采用 overflow: hidden 方式:
.container { overflow: hidden; }
-
BFC可以做什么呢?
-
利用BFC避免外邊距折疊
BFC可能造成外邊距折疊峰髓,也可以利用它來避免這種情況傻寂。BFC產(chǎn)生外邊距折疊要滿足一個(gè)條件:兩個(gè)相鄰元素要處于同一個(gè)BFC中。所以携兵,若兩個(gè)相鄰元素在不同的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包含浮動(dòng)(解決高度塌陷)(計(jì)算BFC的高度時(shí)徐紧,浮動(dòng)元素也參與計(jì)算)
浮動(dòng)元素是會(huì)脫離文檔流的(絕對(duì)定位元素會(huì)脫離文檔流)静檬。如果一個(gè)沒有高度或者h(yuǎn)eight是auto的容器的子元素是浮動(dòng)元素,則該容器的高度是不會(huì)被撐開的并级。我們通常會(huì)利用偽元素(:after或者:before)來解決這個(gè)問題拂檩。BFC能包含浮動(dòng),也能解決容器高度不會(huì)被撐開的問題嘲碧。-
使用BFC避免文字環(huán)繞(BFC的區(qū)域不會(huì)與float box重疊)
對(duì)于浮動(dòng)元素稻励,可能會(huì)造成文字環(huán)繞的情況(Figure1),但這并不是我們想要的布局(Figure2才是想要的)愈涩。要解決這個(gè)問題望抽,我們可以用外邊距,但也可以用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>
造成文字環(huán)繞的原因
在BFC上下文中煤篙,每個(gè)盒子的左外側(cè)緊貼包含塊的左側(cè)(從右到左的格式里,則為盒子右外側(cè)緊貼包含塊右側(cè))毁腿,甚至有浮動(dòng)也是如此(盡管盒子里的行盒子 Line Box 可能由于浮動(dòng)而變窄)辑奈,除非盒子創(chuàng)建了一個(gè)新的BFC(在這種情況下盒子本身可能由于浮動(dòng)而變窄)。
因而已烤,如果p元素創(chuàng)建一個(gè)新的BFC那它就不會(huì)再緊貼包含塊的左側(cè)了鸠窗。 -
在多列布局中使用BFC
如果我們創(chuàng)建一個(gè)占滿整個(gè)容器寬度的多列布局,在某些瀏覽器中最后一列有時(shí)候會(huì)掉到下一行胯究。這可能是因?yàn)闉g覽器四舍五入了列寬從而所有列的總寬度會(huì)超出容器塌鸯。但如果我們?cè)诙嗔胁季种械淖詈笠涣欣飫?chuàng)建一個(gè)新的BFC,它將總是占據(jù)其他列先占位完畢后剩下的空間唐片。
例如: <div class="container"> <div class="column">column 1</div> <div class="column">column 2</div> <div class="column">column 3</div> </div> 對(duì)應(yīng)的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; }
-