如何理解HTML外边距折叠,深入理解 CSS 中的外边距折叠及 BFC

作为一个前端工程师,在编写 CSS 时外边距折叠及 BFC 都是经常遇到的情况,今天就来做一下总结。

外边距折叠

什么是外边距折叠

在 CSS 中,两个或者多个普通流中相邻盒子的边距在垂直方向上会发生折叠的这种现象叫做外边距折叠。外边距折叠分为父子外边距折叠及兄弟外边距折叠。

示例1:父子外边距折叠

我们给 child 添加了 margin-top,却导致 body 整体下移。

d6dd986ab65cfe7397dcc4f616650d26.png

示例2:兄弟外边距折叠

我们给 child1 设置了 margin-bottom:20px,给 child2设置了 margin-top: 50px,但最终的展现效果确实 50px(注意:如果 margin 设置负值的话是什么情况的?可以思考一下😯)

6c6e1d0c0d97a6f7969adbfff02b2e73.png

ae87d5640d74eba9ab19e87a27f6cc1f.png

触发外边距折叠的条件

那么触发外边距折叠的条件是什么呢?W3C文档里已作出了说明,需要符合下面条件:

都是普通流中的元素且属于同一个 BFC

没有被 padding、border、clear 或非空内容隔开

两个或两个以上垂直方向的「相邻元素」

注意这里的「相邻元素」可能是兄弟节点也可能是父子节点,比如:一个元素的 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

什么是 BFC

BFC(Block Formatting Context)即块级格式化上下文,W3C 规范对此作了详细的描述,翻译过来大概如下:

浮动元素和绝对定位元素,非块级盒子的块级容器(例如 inline-blocks, table-cells, 和 table-captions),以及 overflow 值不为visiable 的块级盒子,都会为他们的内容创建新的 BFC(块级格式上下文)。

在 BFC 中,盒子从顶端开始垂直的一个接一个排列,两个盒子之间的垂直间距由他们的 margin 值决定,在同一个 BFC 中,两个相邻块级盒子的垂直外边距会产生折叠。

在 BFC 中,每一个盒子的左外边缘会触碰到容器的左边缘,对于从右到左的格式来说,则触碰到右边缘。即使在浮动里也是这样的(尽管一个盒子的 line boxes 会因为浮动而收缩),除非这个盒子的内部创建了一个新的 BFC(由于浮动,在这种情况下盒子本身 将会变得更窄

Line Box: www.w3.org/TR/2002/WD-…

如何创建一个 BFC

通过上面的描述,创建一个 BFC 只需满足以下条件之一即可:

float 的值不为 none

overflow 的值不为 visible

position 的值不为 static 或者 relative

display 的值为 table-cell, table-caption, inline-block, flex 或 inline-flex 其中之一

例如在本文开篇的第一个父子元素边距折叠的问题,我们只需在父元素上增加 overflow: hidden 触发 BFC 即可:

e4a03283ddcee6df93e50f279fafdf97.png

BFC 的使用

边距折叠的问题可以用 BFC 来解决,但触发 BFC 并不是解决边距折叠的充分条件,还要得到合理的运用,下面就是使用 BFC 来解决的一些问题。

使用 BFC 防止外边距折叠

对于兄弟元素,只要给它们加上 BFC 的外壳,对它们进行隔离,就能使它们的 margin 不折叠,例如:

child1
child1

复制代码

对于父子元素,只要让父级元素触发 BFC,就能使父级的 margin 和当前元素的 margin 不折叠。

使用 BFC 防止高度塌陷

例如我们在一个容器中,对其子元素进行了浮动处理,那么由于子元素脱离文档流,容器的高度会发生塌陷,这个时候就可以通过触发容器的 BFC 来解决。

0a685bc5d4846c8500a1e6e4bbcd45d0.png

可以对示例中的 parent 添加 overflow: hidden 来触发 BFC,从而使容器高度恢复:

6aa143c2f7f8c121152ac44505393c13.png

当然,对于类似问题我们常常会通过 clearfix 清除浮动来解决,以保证普适性,不过 BFC 也不失为一种不错的解决办法。

使用 BFC 防止「文字环绕」

比如如下示例,我们希望 child2位于 child1 的右方,但是此时 child1 与 child2 的一部分却重合了,这并不是我们想要的效果。

decdf8836ab200a73161510bddf7b7fe.png

这是由于在 BFC 中,每一个盒子的左外边缘会触碰到容器的左边缘,对于从右到左的格式来说,则触碰到右边缘,即使在浮动里也是这样的(尽管一个盒子的 line boxes 会因为浮动而收缩)。而这里 p 元素的文本部分就进行了收缩,为浮动元素提供空间。

那么此时为了解决这个问题,只需触发 p 元素的 BFC 即可,比如为 p 元素添加一个 overflow: hidden:

e2f9f4086081e5a5e5b30098d69c3016.png

总结

在 CSS 中,两个或者多个普通流中相邻盒子的边距在垂直方向上会发生折叠的这种现象叫做外边距折叠

可以通过合理的创建 BFC 解决外边距折叠的问题

BFC(Block Formatting Context)即块级格式化上下文,具有 BFC 特性的元素是一个独立的容器,容器里面的元素不会在布局上影响到外面的元素

可以通过如下方式创建 BFC:

float 的值不为 none

overflow 的值不为 visible

position 的值不为 static 或者 relative

display 的值为 table-cell, table-caption, inline-block, flex 或 inline-flex 其中之一

BFC 可以用来解决外边距折叠问题、高度塌陷问题以及「文字环绕」问题等

本文代码示例地址:github.com/taroalan/bl…

相关参考

深入理解CSS外边距折叠(Margin Collapse)

如何解决外边距叠加的问题? - 知乎

10 分钟理解 BFC 原理 - 知乎

css - Why does overflow: hidden have the unexpected side-effect of growing in height to contain floated elements? - Stack Overflow

Floating elements causes the parent to collapse. HTML / CSS - Stack Overflow

margin | CSS-Tricks

Box model

Visual formatting model

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[深入理解 CSS 中的外边距折叠及 BFC]http://www.zyiz.net/tech/detail-140057.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值