深入理解BFC和Margin Collapse

BFC定义

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

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

在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格式来说,则触碰到右边缘)。

Margin Collapse(外边距塌陷/外边距合并)

在CSS当中,相邻的两个盒子(可能是兄弟关系也可能是祖先关系)的外边距可以结合成一个单独的外边距。这种合并外边距的方式被称为塌陷,并且因而所结合成的外边距称为塌陷外边距。

塌陷的结果

  1. 两个相邻的外边距都是正数时,塌陷结果是它们两者之间较大的值。
  2. 两个相邻的外边距都是负数时,塌陷结果是两者绝对值的较大值。
  3. 两个外边距一正一负时,塌陷结果是两者的相加的和。

产生塌陷的必备条件

margin必须是邻接的,而根据w3c规范,两个margin是邻接的必须满足以下条件:

  • 必须是处于常规文档流(非float和绝对定位)的块级盒子,并且处于同一个BFC当中。如果有元素脱离了常规文档流,那么该元素之后的元素和该元素之前的元素可以邻接。
  • 没有线盒,没有空隙(clearance:当浮动元素之后的元素设置clear以闭合相关方向的浮动时会产生。有这个的时候,修改清除浮动元素的margin-top无效),没有padding和border将他们分隔开
  • 都属于垂直方向上相邻的外边距,可以是下面任意一种情况
    • 元素的margin-top与其第一个常规文档流的子元素的margin-top
    • 元素的margin-bottom与其下一个常规文档流的兄弟元素的margin-top
    • 元素的margin-bottom与其最后一个常规文档流的子元素的margin-bottom,同时元素的height设置为auto
    • 高度为0并且最小高度也为0,不包含常规文档流的子元素,并且自身没有建立新的BFC的元素的margin-top和margin-bottom。

以上的条件意味着下列的规则:

  • 创建了新的BFC的元素(例如浮动元素或者’overflow’值为’visible’以外的元素)与它的子元素的外边距不会塌陷
  • 浮动元素不与任何元素的外边距产生塌陷(包括其父元素和子元素)。因为浮动元素产生新的BFC。
  • 绝对定位元素不与任何元素的外边距产生塌陷
  • inline-block元素不与任何元素的外边距产生塌陷
  • 一个常规文档流元素的margin-bottom与它下一个常规文档流的兄弟元素的margin-top会产生塌陷,除非它们之间存在间隙(clearance)。
  • 一个常规文档流元素的margin-top 与其第一个常规文档流的子元素的margin-top产生塌陷,条件为父元素不包含 padding 和 border ,子元素不包含 clearance。
  • 一个 ‘height’ 为 ‘auto’ 并且 ‘min-height’ 为 ‘0’的常规文档流元素的 margin-bottom 会与其最后一个常规文档流子元素的 margin-bottom 塌陷,条件为父元素不包含 padding 和 border ,子元素的 margin-bottom 不与包含 clearance 的 margin-top 塌陷。
  • 一个不包含border-top、border-bottom、padding-top、padding-bottom的常规文档流元素,并且其 ‘height’ 为 0 或 ‘auto’, ‘min-height’ 为 ‘0’,其里面也不包含行盒(line box),其自身的 margin-top 和 margin-bottom 会塌陷。

参考连接

https://www.w3.org/TR/CSS22/box.html#collapsing-margins

CSS: 深入理解BFC和Margin Collapse (margin叠加或者合并外边距)

https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing

分享到