Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.
浮动、绝对定位的元素、块容器(例如inline块、表格单元格和表标题)等非块盒,和“overflow”不为“visible”的块容器(除非这个值被传播到viewport中)会它们的内容建立新的块级格式化上下文。
In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the 'margin' properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.
在块级格式化上下文中,元素框从包含块的顶部一个接一个地放置,margin属性决定了两个兄弟元素间的垂直距离,在同一块级格式化上下文中的相邻块级盒子之间的垂直margin会
In a block formatting context, each box's left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box's line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).
在一个块格式化上下文中,每个框的左外边缘都触及了包含块的左边缘(右到左的格式,右边缘的触摸)。即使在浮动的情况下也是如此(尽管一个框的行框可能会由于浮动而收缩),除非该框建立一个新的块格式化上下文(在这种情况下,由于浮动,box本身可能会变得更窄)。
An inline formatting context is established by a block container box that contains no block-level boxes. In an inline formatting context, boxes are laid out horizontally, one after the other, beginning at the top of a containing block. Horizontal margins, borders, and padding are respected between these boxes. The boxes may be aligned vertically in different ways: their bottoms or tops may be aligned, or the baselines of text within them may be aligned. The rectangular area that contains the boxes that form a line is called a line box.
一内联格式化上下文由一个没有包含块级元素框的块级容器建立,在一个内嵌的格式环境中,框被水平地放置,一个接一个,从一个包含块的顶部开始。在这些框之间,横向的边距、边距和内边距都很受尊重。这些框可以以不同的方式垂直对齐:它们的底部或顶部可以对齐,或者它们之间的文本基线可以对齐。包含组成直线的方框的矩形区域称为线框。
在普通流中,元素按照其在 HTML 中的先后位置至上而下布局,在这个过程中,行内元素水平排列,直到当行被占满然后换行,块级元素则会被渲染为完整的一个新行, 除非另外指定,否则所有元素默认都是普通流定位,也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。
一. BFC 是什么?
有了上面的基础后,可以正式介绍 BFC 了。从样式上看,具有 BFC 的元素与普通的容器没有什么区别,但是从功能上,具有 BFC 的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器没有的一些特性,例如可以包含浮动元素,清除浮动的方法(如 overflow 方法)就是触发了浮动元素的父元素的 BFC ,使到它可以包含浮动元素,从而防止出现高度塌陷的问题。
简单来说,BFC 就是一种属性,这种属性会影响着元素的定位以及与其兄弟元素之间的相互作用。
可以把它想象成一个大箱子,里面装着很多元素,箱子可以隔开里面的元素和外面的元素。好像JS中的闭包,保护其中的元素。它可以包含浮动元素,可以阻止margin折叠,可以防止元素被浮动元素覆盖……
eg:
二.如何触发 BFC
它至少满足以下条件之一:
- float 的值不为 none
- position 的值不为 static 或 relative
- display 的值为 table-cell、table-caption、inline-block、flex 或 inline-flex
- overflow 的值不为 visiable
- 对于 display:table 的元素,产生 block formatting contexts 的是匿名框而不是 display:table。
三.BFC有哪些作用:
- 自适应两栏布局
- 可以阻止元素被浮动元素覆盖
- 可以包含浮动元素——清除内部浮动
- 分属于不同的BFC时可以阻止margin重叠
1.利用BFC可以消除Margin Collapse
在正常情况下,在一个容器内的所有box将会由上至下依次垂直排列,即我们所说的一个元素占一行,并切垂直相邻的距离(即margin)是由各自的margin决定的,而不是两个margin的叠加。
让我们看一个例子:红色的div包含三个绿色的p元素。
HTML代码:
CSS代码:
理想情况下,我们会认为p标签之间的margin应该是它们的和(20px),但实际上却是10px.这其实是collapsing margins。
结果如下:
![](https://images2018.cnblogs.com/blog/1251691/201803/1251691-20180323131743848-1583854794.png)
这似乎让人有点困惑,BFC导致了margin collapse,而现在又要用它来解决margin cllapse.但是始终要记住一点:只有当元素在同一个BFC中时,垂直方向上的margin
才会clollpase.如果它们属于不同的BFC,则不会有margin collapse.因此我们可以再建立一个BFC去阻止margin collpase的发生。
现在HTML变成:
CSS也有改变:
现在的结果为:
![](https://images2018.cnblogs.com/blog/1251691/201803/1251691-20180323131744603-715909466.png)
由于第二个p元素和第三个p元素属于不同的BFC,因此避免了margin collapse.
2.利用BFC去容纳浮动元素
我相信大家经常会遇到一个容器里有浮动元素,但是这个容器的高度却是0的场景,如下图:
看下面的例子:
HTML:
CSS:
结果:
![](https://images2018.cnblogs.com/blog/1251691/201803/1251691-20180323131745285-2510565.png)
在上边的情形中,container是不会有高度的,因为它包含了浮动元素。通常我们解决这个问题的办法是利用一个伪元素去实现clear fix,但是现在我们有了更好的解决办法,即利用BFC,因为它够容纳浮动元素的。
我们现在让container形成BFC规则,结果如下:
结果:
![](https://images2018.cnblogs.com/blog/1251691/201803/1251691-20180323131746217-1555495074.png)
3.利用BFC阻止文本换行
有时候,确切的说大多数情况(若没有特殊设置),文本将会环绕浮动元素(如Figure 1),
但有时候这并不是我们期望的,我们想要的是Figure2。
![](https://images2018.cnblogs.com/blog/1251691/201803/1251691-20180323131747021-1044153695.png)
往往可能大家都会选择利用margin-left来强行让p的容器有一个左边距,而距离恰好为Floated div的宽度,但现在我们可以利用BFC更好的解决这个问题。
首先让我们了解一下文本换行的原理吧:
![](https://images2018.cnblogs.com/blog/1251691/201803/1251691-20180323131747688-38343472.png)
在Figure1中,整个p元素实际上是处于上图中的黑色区域,p元素没有移动是因为它在浮动元素的下方。但实际上p作为行块级别的元素(相对于行内文本)却发生了移动,因为要给float元素’腾’位置,而随着文本的增加,文本高度超过浮动元素的部分则不会在水平方向上收缩内部距离,因此看起来像是环绕。
如图:
![](https://images2018.cnblogs.com/blog/1251691/201803/1251691-20180323131750179-2023879894.png)
在解决这个问题之前,我们先来看一下W3C的规范在这方面的描述:
In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).
W3C为这种情况提供了一个解决方案:unless the box establishes a new block formatting context
,即为p建立BFC。
结果:
![](https://images2018.cnblogs.com/blog/1251691/201803/1251691-20180323131754088-1827602716.png)