之前看张鑫旭老师的《css世界》这本书感觉还不错,总结分享一些出来也方便自己查看~
对于padding,元素设定了width或者保持“包裹性”的时候,会改变元素可视尺寸;但是对于margin则相反,元素设定了width值或者保持“包裹性”的时候,margin对尺寸没有影响,只有元素是“充分利用可用空间”状态的时候,margin才可以改变元素的可视尺寸。
(Ps:包裹性具有包裹和自适应性两个特点,指 元素的尺寸只由内部元素决定,但是永远小于包含块容器的尺寸)
比方说,如下CSS:
.father {
width: 300px;
margin: 0-20px;
}
此时元素宽度还是300像素,尺寸无变化。因为只要宽度设定,margin就无法改变元素尺寸,这和padding是不一样的。
但是,如果是下面这样的HTML和CSS:
<div class="father">
<div class="son"></div>
</div>
.father { width: 300px; }
.son { margin: 0-20px; }
则.son元素的宽度就是340像素了,尺寸通过负值设置变大了,因为此时的宽度表现是“充分利用可用空间”。
或者这么说吧,只要元素的尺寸表现符合“充分利用可用空间”,无论是垂直方向还是水平方向,都可以通过margin改变尺寸。
1、margin的百分比值
和padding属性一样,margin的百分比值无论是水平方向还是垂直方向都是相对于宽度计算的。不过相对于padding, margin的百分比值的应用价值就低了一截,根本原因在于和padding不同,元素设置margin在垂直方向上无法改变元素自身的内部尺寸,往往需要父元素作为载体,此外,由于margin合并的存在,垂直方向往往需要双倍尺寸才能和padding表现一致。例如:
.box {
background-color: olive;
overflow: hidden;
}
.box > div {
margin: 50%;
}
<div class="box">
<div></div>
</div>
结果.box是一个宽高比为2:1的橄榄绿长方形。是不是有点儿奇怪:50%+50%应该是100%,应该上下一样,是1:1的正方形,怎么最后是2:1的长方形呢?这就涉及下面margin合并的内容了。
2、什么是margin合并
块级元素的上外边距(margin-top)与下外边距(margin-bottom)有时会合并为单个外边距,这样的现象称为“margin合并”。
(1)块级元素,但不包括浮动和绝对定位元素,尽管浮动和绝对定位可以让元素块状化。
(2)只发生在垂直方向,需要注意的是,这种说法在不考虑writing-mode的情况下才是正确的,严格来讲,应该是只发生在和当前文档流方向的相垂直的方向上。由于默认文档流是水平流,因此发生margin合并的就是垂直方向。
3、margin合并的3种场景
margin合并有以下3种场景。
(1)相邻兄弟元素margin合并。这是margin合并中最常见、最基本的,例如:
p { margin: 1em 0; }
 <p>第一行</p>
<p>第二行</p >
则第一行和第二行之间的间距还是1em,因为第一行的margin-bottom和第二行的margin-top合并在一起了,并非上下相加。
(2)父级和第一个/最后一个子元素。我们直接看例子,在默认状态下,下面3种设置是等效的:
<div class="father">
<div class="son" style="margin-top:80px; "></div>
</div>

<div class="father" style="margin-top:80px; ">
<div class="son"></div>
</div>

<div class="father" style="margin-top:80px; ">
<div class="son" style="margin-top:80px; "></div>
</div>
那该如何阻止这里margin合并的发生呢?
对于margin-top合并,可以进行如下操作(满足一个条件即可)
• 父元素设置为块状格式化上下文元素;
• 父元素设置border-top值;
• 父元素设置padding-top值;
• 父元素和第一个子元素之间添加内联元素进行分隔。
对于margin-bottom合并,可以进行如下操作(满足一个条件即可):
• 父元素设置为块状格式化上下文元素;
• 父元素设置border-bottom值;
• 父元素设置padding-bottom值;
• 父元素和最后一个子元素之间添加内联元素进行分隔;
• 父元素设置height、min-height或max-height。
4、margin合并的计算规则
我把margin合并的计算规则总结为“正正取大值”“正负值相加”“负负最负值”3句话。下面来分别举例说明。
(1)正正取大值。如果是相邻兄弟合并:
.a { margin-bottom: 50px; }
.b { margin-top: 20px; }
<div class="a"></a >
<div class="b"></a >
此时.a和.b两个<div>
之间的间距是50px,取大的那个值。
如果是父子合并:
.father { margin-top: 20px; }
.son { margin-top: 50px; }
<div class="father">

<div class="son"></div>
</div>
此时.father元素等同于设置了margin-top:50px,取大的那个值。
如果是自身合并:
.a {
margin-top: 20px;
margin-bottom: 50px;
}
<div class="a"></div>
则此时.a元素的外部尺寸是50px,取大的那个值。
(2)正负值相加。如果是相邻兄弟合并:
.a { margin-bottom: 50px; }
.b { margin-top: -20px; }
<div class="a"></a >
<div class="b"></a >
此时.a和.b两个<div>
之间的间距是30px,是-20px+50px的计算值。
如果是父子合并:
.father { margin-top: -20px; }
.son { margin-top: 50px; }
<div class="father">
<div class="son"></div>
</div>
此时.father元素等同于设置了margin-top:30px,是-20px+50px的计算值。
如果是自身合并:
.a {
margin-top: -20px;
margin-bottom: 50px;
}
<div class="a"></div>
则此时.a元素的外部尺寸是30px,是-20px+50px的计算值。
(3)负负最负值。如果是相邻兄弟合并:
.a { margin-bottom: -50px; }
.b { margin-top: -20px; }
<div class="a"></a >
<div class="b"></a >
此时.a和.b两个<div>
之间的间距是-50px,取绝对负值最大的值。
如果是父子合并:
.father { margin-top: -20px; }
.son { margin-top: -50px; }

<div class="father">
<div class="son"></div>
</div>
此时.father元素等同于设置了margin-top:-50px,取绝对负值最大的值。
如果是自身合并:
.a {
margin-top: -20px;
margin-bottom: -50px;
}
<div class="a"></div>
则此时.a元素的外部尺寸是-50px,取绝对负值最大的值。
好啦,上面内容只是书里的冰山一角,分享一下~