Original Author: Ritesh Kumarcss
Original Article: http://www.sitepoint.com/understanding-block-formatting-contexts-in-css/segmentfault
Translator: HaoyCn浏览器
Date: 9th of Aug, 2015ide
块级格式化上下文(Block Formatting Context)是网页CSS视觉渲染的一部分,并用于决定块盒子的布局。在定位体系(Positioning Scheme)中它属于常规流(Normal Flow)。根据W3C所言:wordpress
浮动、绝对定位元素(
position
为absolute
或fixed
)、行内块元素display:inline-block
、表格单元格display:table-cell
、表格标题display:table-caption
以及overflow
属性值不为visible
的元素(除了该值被传播到视点viewport
的状况)将建立一个新的块级格式化上下文。布局
上面的引言差很少总结了一个BFC是如何造成的。但让我们用另一种更通俗易懂的方式来重定义它。一个BFC就是一个HTML盒子,它至少知足如下条件之一:flex
float
的值不为 none
spa
position
的值不为 static
或 relative
翻译
display
的值为 table-cell
、table-caption
、inline-block
、flex
或 inline-flex
code
overflow
的值不为 visiable
一个BFC能够显式触发。若是咱们想建立之,咱们只需给它添加上面提到的任何一个CSS样式。
好比,看下面的HTML:
<div class="container"> Some Content here </div>
一个新的BFC能够经过给容器添加任意一个必要的CSS样式来建立,好比overflow: scroll
,overflow: hidden
,display: flex
,float: left
,或 display: table
。尽管上述条件均可以建立BFC,但也会产生一些其余效果,如:
display: table
可能引起响应性问题
overflow: scroll
可能产生多余的滚动条
float: left
将把元素移至左侧,并被其余元素环绕
overflow: hidden
将裁切溢出元素
因此不管什么时候,当要建立一个BFC时,咱们要基于需求选择最恰当的样式。为了保持一致性,我在本文的全部例子中均使用 overflow: hidden
。
.container { overflow: hidden; }
你能够自由选择使用除 overflow: hidden
以外的其余样式。
W3C规范道:
在BFC上下文中,每一个盒子的左外侧紧贴包含块的左侧(从右到左的格式里,则为盒子右外侧紧贴包含块右侧),甚至有浮动也是如此(尽管盒子里的行盒子
Line Box
可能因为浮动而变窄),除非盒子建立了一个新的BFC(在这种状况下盒子自己可能因为浮动而变窄)。
简单来讲,如上图所示,因此属于BFC的盒子都左对齐(在从左到右的格式下)而且它们的左外侧紧贴包含块的左侧。在最后一个盒子中咱们能够看到尽管左侧存在一个浮动元素(棕色),另一个元素(绿色)仍然紧贴包含块的左侧。该状况的产生原理将在下文关于文字环绕的部分中讨论。
在常规流中,盒子从包含块的顶部开始一个个地垂直摆放。两个同胞盒子间的垂直举例由两个盒子各自的外边距所决定,但不是两者外边距之和。
为便于理解,咱们看个例子。
在上图中,一个红盒子(div
)包含着两个同胞绿元素(p
),一个BFC已经建立了出来。
<div class="container"> <p>Sibling 1</p> <p>Sibling 2</p> </div>
相应的CSS是:
.container { background-color: red; overflow: hidden; /* creates a block formatting context */ } p { background-color: lightgreen; margin: 10px 0; }
理论上两个同胞元素间的外边距应当是两者外边距之和(20px)但实际上倒是10px。这就是众所周知的外边距折叠(Collapsing Margins)。若是同胞元素外边距不一样,将应用最大的那个。
在讨论了上面BFC折叠外边距的状况后,如今说避免折叠可能有点让人摸不着头脑。但咱们必须牢记于心的一件事是,相邻块级盒子(同胞)之间的垂直外边距只有在它们处于同一个BFC时才会发生折叠。若是它们分属于不一样的BFC,就不会折叠了。因此,经过建立新的BFC咱们能够避免外边距折叠。
让咱们在早前的例子中添加第三个同胞元素,如今HTML是:
<div class="container"> <p>Sibling 1</p> <p>Sibling 2</p> <p>Sibling 3</p> </div>
CSS是:
.container { background-color: red; overflow: hidden; /* creates a block formatting context */ } p { background-color: lightgreen; margin: 10px 0; }
结果和上面同样,便是说,折叠仍是会发生而且三个同胞间分隔的垂直距离是10px。这是由于三个 p
标签都从属于同一个BFC。
如今咱们修改第三个同胞元素,使之成为一个新的BFC的一部分。如今的HTML变成了:
<div class="container"> <p>Sibling 1</p> <p>Sibling 2</p> <div class="newBFC"> <p>Sibling 3</p> </div> </div>
CSS:
.container { background-color: red; overflow: hidden; /* creates a block formatting context */ } p { margin: 10px 0; background-color: lightgreen; } .newBFC { overflow: hidden; /* creates new block formatting context */ }
如今输出的结果就有所不一样了:
由于第二个和第三个同胞元素如今分属于不一样的BFC,它们之间就不会发生外边距折叠了。
BFC能够包含浮动。咱们常常遇到容器中含有浮动元素的状况。这种状况下容器元素没有高度而且其浮动子元素脱离了网页的常规流。咱们一般用清除浮动解决这个问题,最广泛的作法就是使用伪元素。但咱们也能够经过建立一个BFC来解决问题。
看个例子:
<div class="container"> <div>Sibling</div> <div>Sibling</div> </div>
CSS:
.container { background-color: green; } .container div { float: left; background-color: lightgreen; margin: 10px; }
在上面这个例子中,容器没有任何高度,而且它包不住浮动子元素。为解决此问题,咱们经过添加 overflow: hidden
来在容器中建立一个新的BFC。修改后的CSS成了:
.container { overflow: hidden; /* creates block formatting context */ background-color: green; } .container div { float: left; background-color: lightgreen; margin: 10px; }
如今容器能够包住浮动子元素,而且其高度会扩展至包住其子元素,在这个新的BFC中浮动元素又回归到页面的常规流之中了。
有时候浮动DIV旁边的文本会环绕它(以下图1所示)而这种状况有时候并不如咱们所愿,咱们想要下图2的效果。要解决这个问题,咱们能够用外边距,但也能够用BFC。
首先让咱们弄明白为什么文字会环绕。要理解这个咱们必须明白,当存在元素浮动的时候,盒模型如何工做。这就是我早先讨论BFC中对齐时候的遗留问题。咱们经过下图来看图1到底发生了什么。
假设HTML是:
<div class="container"> <div class="floated"> Floated div </div> <p> Quae hic ut ab perferendis sit quod architecto, dolor debitis quam rem provident aspernatur tempora expedita. </p> </div>
上图整个黑色区域表示 p
元素,如咱们所见,p
元素没有移位但它叠在了浮动元素之下,而p
元素的行盒子(即文本行)却移位了,行盒子水平变窄来给浮动元素腾出了空间。
随着文本的增长,最后文本将环绕在浮动元素之下,由于那时候行盒子再也不须要移位,也就成了图1的样子。这就是为何即使有浮动元素,段落仍紧贴包含块的左侧,而行盒子会变窄来给浮动元素腾位子。
若是咱们能位移整个 p
元素,这个环绕问题也就迎刃而解了。
在说解决方案以前,咱们再回顾下W3C规范:
在BFC上下文中,每一个盒子的左外侧紧贴包含块的左侧(从右到左的格式里,则为盒子右外侧紧贴包含块右侧),甚至有浮动也是如此(尽管盒子里的行盒子
Line Box
可能因为浮动而变窄),除非盒子建立了一个新的BFC(在这种状况下盒子自己可能因为浮动而变窄)。
据此,若是 p
元素建立一个新的BFC那它就不会再紧贴包含块的左侧了。给 p
元素添加 overflow: hidden
就能垂手可得地办到。这解决了文本环绕浮动对象的问题。
若是咱们建立一个占满整个容器宽度的多列布局,在某些浏览器中最后一列有时候会掉到下一行。这多是由于浏览器四舍五入了列宽从而全部列的总宽度会超出容器。但若是咱们在多列布局中的最后一列里建立一个新的BFC,它将老是占据其余列先占位完毕后剩下的空间。
咱们来举个三列布局的例子:
这是HTML:
<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; }
如今尽管盒子的宽度稍有改变,但布局不会打破。固然,对多列布局来讲这不必定是个好办法,但能避免最后一列下掉。这个问题上弹性盒或许是个更好的解决方案,但这个办法能够用来讲明元素在这些环境下的行为。
我但愿本文已经向你展现了BFC的特性以及BFC是如何影响页面上的元素的视图定位的。展现其用法的例子应该有让BFC显得更透彻一些。
若是你有任何想要补充的,请在评论里留言。若是你想更深刻了解的话,必定得去回顾W3C对这个话题的详述。
本文中说起的浮动与行盒子变窄问题深刻探讨,能够参看博文:http://www.zhangxinxu.com/wordpress/?p=583
W3C标准中“除了该值被传播到视点 viewport
的状况”,能够参看问题:http://segmentfault.com/q/1010000002645174
转载本文亦请同时注明原出处(见本文顶部)。如您承认本文翻译,欢迎推荐或收藏,谢谢!