外边距合并
w3介绍这个问题地址:https://www.w3.org/TR/CSS2/box.html#collapsing-margins
当两个垂直方向
外边距相遇
,它们将形成一个折叠外边距
。
合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者。
为了好认识,我们称内部div为"盒子",包含这个内部div的外部div为"包含体"
解释
- 怎么相遇:
- 相邻的两个盒子(可能是兄弟关系也可能是包含关系)
这两个元素margin之间不能夹杂着边框啊,补白啊什么的就算margin相遇,这点很重要
- 相邻的两个盒子(可能是兄弟关系也可能是包含关系)
- 哪个方向
- 一定为垂直方向,水平方向没有
- 形成一个折叠外边距过程
- 盒子margintop和包含体margintop取出
最终折叠外边距值
。下面为取这个值的情况
150 50=150
150 -50=100
-150 -50 =-150
-150 50 =-100
- 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
可以在下面例子2中,改变一下
- 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
- 两个外边距一正一负时,折叠结果是两者的相加的和。
- 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
- 包含关系时,
盒子不显示margin-top(相当没有margin-top),包含体显示margin-top这个最终值。
- 兄弟关系时,两兄弟之间的margin共用这个最终值。
- 盒子margintop和包含体margintop取出
极限情况一个元素
- 当一个块元素,没有补白和填充,上外边距与下外边距就碰到了一起,它们也会发生合并。
例子1包含关系,保证相遇,不设置外层div的内边距(补白)和边框的前提!
<meta charset="utf-8">
<style type="text/css">
* {margin:0;padding:0;border:0;}
#outer {200px;height:200px;background-color:red;margin-top:-20px;}
#inner {50px;height:50px;background-color:blue;margin-top:50px;}
</style>
<div id="outer">
<div id="inner">
</div>
</div>
<!--不设置 div 的内边距和边框,那么内部 div 的上外边距将与外部 div 的上外边距合并(叠加),内部div箱单更木有margin-top。外部用这个最大值。-->
例子2兄弟关系
* {margin:0; padding:0;border:0;}
#d1 {100px;height:100px;margin-top:50px;margin-bottom:50px;background-color:red;}/*改变margin-bottom:-50px;试一试*/
#d2 {100px;height:100px;margin-top:10px;background-color:blue;}
<div id="d1">
</div>
<div id="d2">
</div>
<!--两个 div 之间的外边距是 50px,并不是 60px(50px + 10px)。-->
例子3本身合并``它有外边距,但是没有边框或填充。在这种情况下,上外边距与下外边距就碰到了一起,它们会发生合并:
* {margin:0; padding:0;border:0;}
#d1{border: 1px solid red; 200px;}
#d2 {height:0px;min-height:0px;margin-top:50px;margin-bottom:150px;}/*border: 1px solid red;试一试将这个盒子边框加上,是不是还能合并。答案不能!*/
<div id="d1">
<div id="d2"></div>
</div>
从图中可以看到这个红色边框包裹的高度是150px,不是200px。包含体本身木有高度,随着盒子的最后得到的折叠margin自动撑开。
例子3调试注意
但是在浏览器调试的时候,监视盒子的时候,并不是给我们显示折叠margin值
。而是显示这个盒子的设定值
。这点不要影响,最终的折叠margin值的肯定。
例子3Question!!求答案,想了一下午。
减轻上面的影响请试一试一下代码
* {margin:0; padding:0;border:0;}
#d2 {height:0px;min-height:0px;margin-top:50px;margin-bottom:150px;}
<div id="d2"></div>
从上面注意我们知道:调试的时候选中这个元素,显示200px是正常的,但是这个元素距离浏览器上面100px,这个我真不能理解
。
还记得段落之间的margin折叠吗?
不能产生折叠边距的情况重点。
让其中一个或则全部节点脱离常规文档流1浮动不为none,2定位absolute、fixed
,还有一个display:'block', 'list-item', 和 'table'以外的属性
1,浮动元素
、绝对定位
、固定元素
,inline-block元素
不与任何元素的外边距产生折叠(包括其父元素和子元素)
inline-block不符合w3c规范所说元素必须是块级盒子的条件,因为规范中又说明,块级盒子的display属性必须是以下三种之一:'block', 'list-item', 和 'table'。
https://www.w3.org/TR/CSS2/visuren.html#block-boxes
2,保证其不相遇,中间有border或者padding大于0的值,有线盒,有空隙(clearance
|闭合浮动的元素会在其margin-top以上产生一定的空隙
|https://www.w3.org/TR/CSS2/visuren.html#clearance
)
试验
这个分两种情况,是元素之间是包含还是兄弟关系。记得一定要区分开是哪一种情况,这点很重要
一、包含关系不产生折叠1,在包含体元素创建BFC``2,仅仅在盒子(子元素)创建BFC
1.在包含体元素创建BFC,包含体只要创建好BFC,就不会它的子元素不会发生折叠。
display:table-cell除外,有这样的属性的div,不论设不设置margin等多少,f12的时候,都是没有margin的
2.仅仅在盒子(子元素)创建BFC`
* {margin:0;padding:0;border:0;}
body{background: green;}
#outer {200px;height:200px;background-color:red;margin-top:20px;}
#inner {50px;height:50px;background-color:blue;margin-top:50px;}
/*阻止display: table-caption;display:inline-flex;display: inline-block;*/
/*阻止float: left;float: right;(浮动右边)*/
/*阻止position: absolute;position: fixed;*/
/*不能阻止overflow: hidden;*/
/*不能阻止display:flex;*/
/*不能阻止display: table-cell;折叠成20px*/
<div id="outer">
<div id="inner">
</div>
</div>
二、兄弟节点不产生折叠在#d1上加这些属性出现的现象解决不了
* {margin:0; padding:0;border:0;}
#d1 {100px;height:100px;margin-top:50px;margin-bottom:50px;background-color:red;}
#d2 {100px;height:100px;margin-top:50px;background-color:blue;float: left;}
/*在#d2依次加上下面属性*/
/*阻止折叠position: absolute;position: fixed;*/
/*阻止折叠float: left;float: right;可能元素浮动*/
/*阻止折叠display: inline-block;display: table-caption;display:inline-flex*/
/*不能阻止overflow: hidden;*/
/*不能阻止display: table-cell;display:flex;*//*这几个虽然能创建BFC,但是不能阻止折叠!*/
<div id="d1">
</div>
<div id="d2">
</div>
总结 去除折叠和BFC没有绝对的关系
1,在包含体元素创建BFC,不和它的子元素发生 margin 折叠(注意这里指的是创建了BFC的元素和它的子元素不会发生折叠)
2,兄弟关系,设置浮动左右,定位绝对、固定,display不等block', 'list-item', 和 'table。书上建议我们在不想折叠的那一个元素外面套一个BFC元素。