这是前面写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>
在现在的比较新版的浏览器的效果图如下:
(这里粉色的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框模型