关于collapsed margin(外边距合并)

  这是前面写postion定位时写到最后面的例子的时候发现的一个问题,于是专门写一篇随笔来解释记录一下,毕竟两个知识点同时写在一篇文章里面有点混乱的感觉。。

  上篇随笔position定位遇到的问题在这里重新展示出来,代码如下:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title></title>
 5     <script type="text/javascript" src="jquery.js"></script>
 6     <style type="text/css">
 7         div{
 8             width: 100px;
 9             height: 100px;
10             margin-top: 20px;
11             background-color: red;
12         }
13         span{
14             position: relative;
15             display: block;
16             width: 100px;
17             height: 100px;
18             background-color: pink;
19             margin-top: -40px;
20         }
21     </style>
22     <script type="text/javascript">
23     
24     </script>
25 </head>
26 <body>
27     <div>
28         <span></span>
29     </div>
30 </body>
31 </html>
View Code

  在现在的比较新版的浏览器的效果图如下:

  (这里粉色的height为80px;)

  现在来解释一下原因(这里遇到的一个问题是外边距合并的问题):

  collapsed margin:外边距合并。详细解释可以看: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.

  中文解释:在CSS中,两个或多个毗邻(父子元素或兄弟元素)的普通流中的块元素垂直方向上的 margin 会发生叠加。这种方式形成的外边距即可称为外边距叠加(collapsed margin)。

  毗邻:没有被非空内容、padding、border 或 clear 分隔开的两个元素(可以是父子关系或者兄弟关系,只要相邻即可)。

  普通流:除浮动( float )、绝对定位( absolute )外的代码。

  下面几种情况算是毗邻:

  (1)top margin of a box and top margin of its first in-flow child

    一个元素的 margin-top 和它的第一个子元素的 margin-top

  (2)bottom margin of box and top margin of its next in-flow following sibling

    普通流中一个元素的 margtin-bottom 和它的紧邻的兄弟元素的的 margin-top

  (3)bottom margin of a last in-flow child and bottom margin of its parent if the parent has ‘auto’ computed height

    一个元素( height 为 auto )的 margin-bottom 和它的最后一个子元素的margin-bottom

  (4)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

    一个没有创建 BFC、没有子元素、height 为0的元素自身的 margin-top 和 margin-bottom

  上网找了一下图片说明一下:

  • 兄弟元素

  

  • 父子元素

  

  • 空元素

  

  • 以上三种混合

  

  

  现在可以解释最前面遇到的问题了:

  在上面的代码中,之所以父元素div和子元素span会重叠并且看到的实际高度只有80px,就是因为div的margin-top:20px;与span的margin-top:-40px;发生重叠,剩下-20px,而此时的margin-top:-20px;就会被认为是父元素div的外边距了,所以才会整体向上移动20px的距离。

(注意:这里因为两个外边距一个是负一个是正,所以刚好叠加只剩下-20px,而不是比较得到比较大的数作为外边距的值)

* 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值
* 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值
* 两个外边距一正一负时,折叠结果是两者的相加的和

  

  应该如何避免这种情况:

  官网如下说:

  • Margins between a floated box and any other box do not collapse (not even between a float and its in-flow children).
  • Margins of elements that establish new block formatting contexts (such as floats and elements with 'overflow' other than 'visible') do not collapse with their in-flow children.
  • Margins of absolutely positioned boxes do not collapse (not even with their in-flow children).
  • Margins of inline-block boxes do not collapse (not even with their in-flow children).
  • The bottom margin of an in-flow block-level element always collapses with the top margin of its next in-flow block-level sibling, unless that sibling has clearance.
  • The top margin of an in-flow block element collapses with its first in-flow block-level child's top margin if the element has no top border, no top padding, and the child has no clearance.
  • The bottom margin of an in-flow block box with a 'height' of 'auto' and a 'min-height' of zero collapses with its last in-flow block-level child's bottom margin if the box has no bottom padding and no bottom border and the child's bottom margin does not collapse with a top margin that has clearance.
  • A box's own margins collapse if the 'min-height' property is zero, and it has neither top or bottom borders nor top or bottom padding, and it has a'height' of either 0 or 'auto', and it does not contain a line box, and all of its in-flow children's margins (if any) collapse.

  即:

  • 浮动元素和其他任何元素之间不发生外边距叠加 (包括和它的子元素).
  • 创建了 BFC 的元素不会和它的子元素发生外边距叠加
  • 绝对定位元素和其他任何元素之间不发生外边距叠加(包括和它的子元素).
  • inline-block 元素和其他任何元素之间不发生外边距叠加 (包括和它的子元素).
  • 普通流中的块级元素的 margin-bottom 永远和它相邻的下一个块级元素的 margin-top 叠加(除非相邻的兄弟元素clear)
  • 普通流中的块级元素(没有 border-top、没有 padding-top )的 margin-top 和它的第一个普通流中的子元素(没有 clear )发生 margin-top 叠加
  • 普通流中的块级元素( height 为 auto、min-height 为 0、没有 border-bottom、没有 padding-bottom )和它的最后一个普通流中的子元素(没有自身发生 margin 叠加或 clear )发生 margin-bottom 叠加
  • 如果一个元素的 min-height 为 0、没有 border、没有 padding、高度为 0 或者 auto、不包含子元素,那么它自身的外边距会发生叠加

  总结:

  • 兄弟元素间设置 float 或 inline-block 或 absolute
  • 为父元素设置 BFC 或 padding 或 border
  • 设置margin时最好用同一个方向,要不都 top 要不都 bottom.

2016-8-5补充:

   当父元素里面包含的两个子元素是浮动的话,那么该父元素不会包裹子元素,即不会被子元素撑开,解决的方式就是:为父元素设置overflow:hidden或浮动父元素。采用这种方式的根本原因在于创建BFC的元素,子浮动元素也会参与其高度计算,即不会产生高度塌陷问题。实际上只要让父元素生成BFC即可,并不只有这两种方式。

哪些情况会产生BFC:

  • 根元素

  • float属性不为none

  • position为absolute或fixed

  • display为inline-block, table-cell, table-caption, flex, inline-flex

  • overflow不为visible

  参考资料:css框模型

  

原文地址:https://www.cnblogs.com/loveya/p/5458769.html