目录
1、常见定位方案
在讲 BFC 之前,先来了解一下常见的定位方案,定位方案是控制元素的布局,有三种常见方案:
(1)普通流 (normal flow)
在普通流中,元素按照其在 HTML 中的先后位置至上而下布局,在这个过程中,行内元素水平排列,直到当行被占满然后换行,块级元素则会被渲染为完整的一个新行,除非另外指定,否则所有元素默认都是普通流定位,也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定
(2)浮动 (float)
在浮动布局中,元素首先按照普通流的位置出现,然后根据浮动的方向尽可能的向左边或右边偏移,其效果与印刷排版中的文本环绕相似。
(3)绝对定位 (absolute positioning)
在绝对定位布局中,元素会整体脱离普通流,因此绝对定位元素不会对其兄弟元素造成影响,而元素具体的位置由绝对定位的坐标决定。
2、BFC 是个啥?
BFC(Block formatting context)块级格式化上下文:是 W3C CSS2.1 规范中的一个概念,它属于上述定位方案的普通流。它是页面中的一块独立的渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。
块格式化上下文对浮动定位与清除浮动都很重要,浮动定位和清除浮动时只会应用于同一个 BFC 内的元素。浮动不会影响其它 BFC 中元素的布局,而清除浮动只能清除同一 BFC 中在它前面的元素的浮动。外边距折叠也只会发生在属于同一 BFC 的块级元素之间。通俗一点来讲,可以把 BFC 理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。
3、创建 BFC 的方式
块格式化上下文包含创建它的元素内部的所有内容,只要元素满足下面任一条件即可触发 BFC 特性:
<html> 或 <body> 根元素 |
浮动元素(元素的 float 值不是 none) |
绝对定位元素(元素的 position 为 absolute 或 fixed) |
display 为 inline-block(行内块元素)、table-cell(表格单元格)、table-caption(表格标题)、flex(弹性元素)、grid(网格元素) |
overflow 除了 visible 以外的值 (hidden、auto、scroll) |
contain 值为 layout、content 或 paint 的元素 |
4、BFC 特性及应用
(1)BFC内的元素垂直方向会发生边距重叠
从效果上看,因为两个 div 元素都处于同一个 BFC 容器下 (这里指 body 元素) 所以第一个 div 的下边距和第二个 div 的上边距发生了重叠,所以两个盒子之间距离只有 100px,而不是 200px。可设置元素的 display 属性为 inline-block 消除这种现象。
ps:块元素的第一个(最后一个)子元素的 margin 和父元素的 margin 也会发生合并现象,可以通过给父元素设置 border 、 padding 或添加 overflow :hidden 消除这种现象。
这不是 bug,而是一种 CSS 的规范,如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中,如上右图所示,通过overflow:hidden 触发 BFC,这样即可避免两个元素边距重叠。
(2)BFC在计算高度时会把浮动元素计算进去
我们都知道,浮动的元素会脱离普通文档流,导致父元素高度塌陷,例如下面的情况一,由于容器内元素浮动,脱离了文档流,所以容器只剩下 2px 的边距高度。如果触发容器的 BFC,那么容器将会包裹着浮动元素,这是因为 BFC 在计算高度时会把浮动元素计算进去
<div style="border: 1px solid #000;"><!--情况一-->
<div style="width: 100px;height: 100px;background: #eee;float: left;"></div>
</div>
<div style="border: 1px solid #000;overflow: hidden"><!--情况二:开启BFC-->
<div style="width: 100px;height: 100px;background: #eee;float: left;"></div>
</div>
(3)BFC元素和浮动元素不会发生重叠
<div style="height: 100px;width: 100px;float: left;background: lightblue">向左浮动的div</div><!--情况一-->
<div style="width: 200px; height: 200px;background: #eee">
由于上一个div向左浮动会脱离文档流,则导致该div会顶上去,占据上一个div的原来位置
</div>
<div style="height: 100px;width: 100px;float: left;background: lightblue">向左浮动的div</div><!--情况二:开启BFC-->
<div style="width: 200px; height: 200px;background: #eee;overflow: hidden;">
通过overflow: hidden;触发该div的BFC,BFC元素和浮动元素不会发生重叠,于是乎
</div>
第一种情况由于上一个 div 向左浮动会脱离文档流,则导致第二个 div 会顶上去,占据第一个 div 的原来位置(文本信息不会被浮动元素所覆盖) ,如果想避免上面这种重叠情况,可在第二个元素中加入 overflow: hidden 触发第二个元素的 BFC 特性,BFC 元素和浮动元素不会发生重叠。
5、总结
BFC在页面是个独立的容器,里外元素互不影响 |
BFC内的元素垂直方向会发生边距重叠 |
BFC在计算高度时会把浮动元素计算进去 |
BFC元素和浮动元素不会发生重叠 |