BFC布局

BFC(Block, Formatting context)块级格式化上下文,它规定了渲染规则,是块盒子布局过程发生的区域。

Box是CSS布局的基本对象和单位。一个页面由很多个BOX组成,不同的类型的Box会参与不同的Formatting context(即如何被渲染)。

Box类型:block-level box(display:block)、inline-level box(display:inline)。

Formatting context是页面渲染上下文。

BFC布局规则

  1. 内部的Box会在垂直方向,一个接一个地放置。

  2. Box垂直方向距离由margin决定。在同一个BFC的两个相邻Box的margin会发生重叠,非同一BFC就不会重叠。

    可以看到下面例子中两个div aside和main之间的margin只有50px。在main外面加上out-main这个div,同时让out-main成为BFC后,main和aside的margin就不会重叠了。

  3. 计算BFC高度时,浮动元素也参与计算。

  4. 不会与float box重叠,也就是这个元素不会被float的元素覆盖。下面的例子就是通过overflow:hidden将main变为BFC,这样aside就不会挡住main。这也就是清除浮动的原理。

  5. BFC是页面上的独立容器,容器里面的子元素不会影响到外面的元素,同样外面的元素(浮动元素)也不会影响容器。

生成BFC

下面列的方式会创建块格式化上下文:

  1. 根元素(<html>)
  2. 浮动元素(float 不是none),这也就是浮动外层元素来清除内部元素的浮动。
  3. 绝对定位元素(position: absolute)
  4. 行内块元素(display:inline-block)
  5. overflow不会visible的块级元素。
  6. display: flow-root
  7. display:flex的子元素
  8. display:grid的子元素
  9. 表格单元格(display:table-cell)

浮动问题

问题1. 浮动元素的高度大于父元素

当浮动元素的高度大于父元素,会出现浮动元素超出父元素。这里将父元素设置为BFC,就可以包含进浮动元素,因为BFC计算高度时会考虑浮动元素。

问题2.后面的元素因为前面的浮动而提前

比如这里的footer如果不使用clear:left,那么它就会为了围绕浮动的侧边栏而被提前到content后面。

问题3.同一BFC的元素外边距合并

当一个BFC中两个元素相交的地方有外边距,那么外边距合并。child和parent的margin-top会重叠。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div class="parent">
<div class="child">
</div>
</div>
<style>
.child {
margin-top: 50px;
height: 200px;
width: 200px;
background: #eee;
}
.parent {
margin-top: 50px;
}
</style>

外边距合并问题出现在:

  1. 相邻元素之间
  2. 父元素与其第一或最后一个元素之间,对于第一个元素使用BFC可以解决,而最后一个元素需要设置父元素的padding-bottom或者border-bottom、height、max-height等设置让最后一个元素强制与父元素的下边框分离,这样margin-bottom就不会重叠了。
  3. 空的块级元素

参考

  1. mdn BFC https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context
  2. [布局概念] 关于CSS-BFC深入理解 https://juejin.im/post/5909db2fda2f60005d2093db