作为一个前端工程师,在编写 CSS 时外边距折叠及 BFC 都是经常遇到的情况,今天就来做一下总结。
在 CSS 中,两个或者多个普通流中相邻盒子的边距在垂直方向上会发生折叠的这种现象叫做外边距折叠。外边距折叠分为父子外边距折叠及兄弟外边距折叠。
我们给 child 添加了 margin-top,却导致 body 整体下移。
我们给 child1 设置了 margin-bottom:20px,给 child2设置了 margin-top: 50px,但最终的展现效果确实 50px(注意:如果 margin 设置负值的话是什么情况的?可以思考一下)
那么触发外边距折叠的条件是什么呢?W3C文档( www.w3 组织网/TR/CSS22/box.html#collapsing-margins)里已作出了说明,需要符合下面条件:
注意这里的「相邻元素」可能是兄弟节点也可能是父子节点,比如:一个元素的 margin-top 和它的第一个普通流子元素的 margin-top;一个元素的 margin-bottom 和它下一个普通流兄弟的 margin-top;一个高度为 auto 元素的 margin-bottom 和它的最后一个子元素的 margin-bottom
前面已经提到了触发外边距折叠的条件,如果要避免外边距折叠只需破坏掉触发的条件即可,比如创建一个 BFC。
对于创建 BFC 的详细方法,引用 知乎用户的回答 就是:
根据 BFC 的定义,两个元素只有在同一 BFC 内,才有可能发生垂直外边距的重叠,包括相邻元素、嵌套元素。要解决 margin 重叠问题,只要让它们不在同一个 BFC 内就行。对于相邻元素,只要给它们加上 BFC 的外壳,就能使它们的 margin 不重叠;对于嵌套元素,只要让父级元素触发 BFC,就能使父级 margin 和当前元素的 margin 不重叠。
当然也要规范写法,比如设置 margin 时,尽量使各个元素 margin 方向保持一致,这样也能提高 CSS 代码的可读性。
那么什么是 BFC 呢?以及如何创建一个 BFC 呢?接下来就来详细看一下。
BFC(Block Formatting Context)即块级格式化上下文,W3C 规范( www.w3 组织网/TR/CSS22/visuren.html#block-formatting)对此作了详细的描述,翻译过来大概如下:
Line Box: www.w3 组织网/TR/2002/WD-css3-linebox-20020515/#LineBox
通过上面的描述,创建一个 BFC 只需满足以下条件之一即可:
例如在本文开篇的第一个父子元素边距折叠的问题,我们只需在父元素上增加 overflow: hidden 触发 BFC 即可:
边距折叠的问题可以用 BFC 来解决,但触发 BFC 并不是解决边距折叠的充分条件,还要得到合理的运用,下面就是使用 BFC 来解决的一些问题。
对于兄弟元素,只要给它们加上 BFC 的外壳,对它们进行隔离,就能使它们的 margin 不折叠,例如:
<div class="parent">
<div class="bfc">
<div class="child child1">child1</div>
</div>
<!-- 本示例中只对其中一个加 bfc 外壳也可以,保证不在同一个 bfc 中-->
<div class="bfc">
<div class="child child2">child1</div>
</div>
</div>
复制代码
对于父子元素,只要让父级元素触发 BFC,就能使父级的 margin 和当前元素的 margin 不折叠。
例如我们在一个容器中,对其子元素进行了浮动处理,那么由于子元素脱离文档流,容器的高度会发生塌陷,这个时候就可以通过触发容器的 BFC 来解决。
可以对示例中的 parent 添加 overflow: hidden 来触发 BFC,从而使容器高度恢复:
当然,对于类似问题我们常常会通过 clearfix 清除浮动来解决,以保证普适性,不过 BFC 也不失为一种不错的解决办法。
比如如下示例,我们希望 child2位于 child1 的右方,但是此时 child1 与 child2 的一部分却重合了,这并不是我们想要的效果。
这是由于在 BFC 中,每一个盒子的左外边缘会触碰到容器的左边缘,对于从右到左的格式来说,则触碰到右边缘,即使在浮动里也是这样的(尽管一个盒子的 line boxes 会因为浮动而收缩)。而这里 p 元素的文本部分就进行了收缩,为浮动元素提供空间。
那么此时为了解决这个问题,只需触发 p 元素的 BFC 即可,比如为 p 元素添加一个 overflow: hidden:
本文代码示例地址: github /wangchi/blog/tree/master/css/bfc

