Lasy

前端开发攻城狮~

外边距折叠(margin collapse)

定义

W3C的定义

In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.

大意是:

两个或多个盒子 邻接的外边距会结合成一个外边距。这种情况就是外边距折叠

重点是:邻接的外边距

折叠/合并后的外边距计算规则

  • 两者都是正数或者都是负数或者存在0,取绝对值较大的一个。
  • 两者一正一负,取两者之和。

产生条件

条件:邻接的外边距

根据W3C,两个外边距邻接(adjoining)的条件是:

Two margins are adjoining if and only if:

  • both belong to in-flow block-level boxes that participate in the same block formatting context
  • no line boxes, no clearance, no padding and no border separate them (Note that certain zero-height line boxes (see 9.4.2) are ignored for this purpose.)
  • both belong to vertically-adjacent box edges, i.e. form one of the following pairs:
    • top margin of a box and top margin of its first in-flow child
    • bottom margin of box and top margin of its next in-flow following sibling
    • bottom margin of a last in-flow child and bottom margin of its parent if the parent has ‘auto’ computed height
    • top and bottom margins of a box that does not establish a new block formatting context and that has zero computed ‘min-height’, zero or ‘auto’ computed ‘height’, and no in-flow children

1.两个边距都属于 流内(in-flow)同一BFC(块级格式化上下文)中的块级元素。
1.没有line boxes、clearance、内边距(padding)或者边框(border)将它们分开。
1.两个边距都是垂直相邻的外边距。包括以下几种类型:
1.一个盒子的top margin和其第一个流内的 子元素top margin
1.一个盒子的bottom margin和其第一个流内的 兄弟元素top margin
1.一个height: auto的元素的bottom margin和其最后一个流内的 子元素bottom margin
1.没有新建BFC、min-height: 0height: auto并且没有在流内的子元素的盒子的top marginbottom margin

所以说,发生外边距折叠的外边距要满足以上三个条件。
在满足前两个条件的基础上,可以将产生条件总结成三种情况:

1. 相邻元素之间

结果是div1div2之间的距离为15px(都是正数,15>10)。

如果改成:

结果是div1div2之间的距离为-15px(都是负数,15>10)。

如果改成:

结果是div1div2之间的距离为5px(一正一负,-10+15=5)。

2. 嵌套元素

结果是containeritem的实际上边距为50px。

3. 空的块级元素

通过next的位置可以看出,next距离顶端20px,所以结果是collapse的实际上(下)边距为20px。

(在我的github上有上述demo的完整代码。)

避免外边距折叠

也就是破坏外边距折叠产生的条件,破坏以下任一都可以避免外边距折叠:

  • 流内
  • 同一BFC
  • 块级元素
  • 没有line boxes、clearance、内边距(padding)或者边框(border)将它们分开。
  • 垂直相邻

需要先解释几个概念:流、BFC

An element is called out of flow if it is floated, absolutely positioned, or is the root element. An element is called in-flow if it is not out-of-flow. The flow of an element A is the set consisting of A and all in-flow elements whose nearest out-of-flow ancestor is A.

翻译一下:

如果元素设置了浮动的、绝对定位或者是根元素,那么就说这个元素在流外(out-of-flow)
不是流外的元素就是流内(in-flow)
元素A的流(flow)指的是A和所有最近流外祖先元素是A的元素组成的集合。

值得注意的是,根元素是流外元素,所以,所有元素都不会和根元素发生外边距折叠。

BFC(块级格式化上下文)

BFC:

Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with ‘overflow’ other than ‘visible’ (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

也就是说,以下设置会形成新的BFC

  • 浮动、绝对定位的元素
  • 不是块级盒子的块级容器(如:inline-blocks,table-cells,table-captions)。
  • overflow:属性不是visible的块级盒子。

只有在同一BFC内的两个块级元素才会发生外边距折叠。

方案

1. 设置浮动、绝对定位

适应类型:

  • 相邻元素
  • 嵌套元素
  • 空的块级元素

相邻元素、嵌套元素:对任何一个元素设置float: leftfloat: rightposition: absolute,但是要注意浮动可能会影响位置;
空的块级元素:对该元素设置float: leftfloat: rightposition: absolute

破坏条件:

  • 流内。浮动或绝对定位使元素成为流外元素。流外元素不发生外边距折叠。

2. 嵌套父级元素并使之产生新的BFC

给其中一个元素外层嵌套一个父级元素,并给该父级元素设置overflow:visible以外的值或者display: inline-blockdisplay: table-celldisplay: table-caption或设置浮动、绝对定位。

适应类型:

  • 相邻元素
  • 嵌套元素

破坏条件:

  • 同一BFC。该元素新增的父级元素产生了新的BFC,该元素属于新增的父元素产生的BFC。

3. 设置display为block、list-item、table以外的值

带来影响最小的是设置成display: inline-block

适用类型:

  • 相邻元素
  • 嵌套元素
  • 空的块级元素

相邻元素、嵌套元素:对任何一个元素设置display: inline-block
空的块级元素:对该元素设置display: inline-block

破坏条件:

  • 块级元素。只有块级元素才会发生外边距折叠。

4. 设置边框border或者内边距padding

适用类型:

  • 嵌套元素
  • 空的块级元素

嵌套元素:只需设置发生外边距折叠的任何一个border为正值即可。或者设置父元素的padding为正值。
空的块级元素:设置上下任一border为正值。或者设置上下任一padding为正值。

破坏条件:

  • 没有line boxes、clearance、内边距(padding)或者边框(border)将它们分开。边框和内边距将发生折叠的外边距分开,使两者不再邻接。

5. 在两个边框之间增加元素

适用类型:

  • 相邻元素
  • 嵌套元素
  • 空的块级元素

破坏条件:

  • 没有line boxes、clearance、内边距(padding)或者边框(border)将它们分开。line boxes(增加的元素)将发生折叠的外边距分开,使两者不再邻接。

以上便是关于外边距折叠的所有内容。
本文中还提到了clearance,但是clearance对外边距叠加的影响需要一定的篇幅来介绍,我准备再写一篇文章单独介绍clearance对外边距叠加的影响。

参考:

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注