深⼊理解css中的margin属性
html里的float是什么意思之前我⼀直认为margin属性是⼀个⾮常简单的属性,但是最近做项⽬时遇到了⼀些问题,才发现margin属性还是有⼀些“坑”的,下⾯我会介绍margin的基本知识以及那些“坑”。这篇博⽂主要分为以下⼏个部分:
第⼀部分:margin--基础知识
  要介绍margin的基础知识,我们不可回避地要谈到css盒⼦模型(Box Model),⼀般⽽⾔,css盒⼦模型是⽤来设计和布局的。它本质上是⼀个盒⼦,包括:外边距(margin)、边框(border)、内边距(padding)以及最中间的内容(content)。下图即为盒⼦模型(这⾥只谈W3C规范的标准盒模型,⽽不谈IE5和IE6在怪异模式中使⽤的⾮标准的盒⼦模型):
  我们要介绍的margin在最外层,因为margin(外边距)⼀定是透明的,所以它可以⽤来使得不同的盒⼦之间留有⼀定的间隙从⽽达到布局美观等效果。从上⾯的盒⼦模型中我们可以看到,margin在四周均存在,我们可以使⽤margin-top、margin-right、margin-bottom、margin-left分别设置这四个⽅向的margin值。(注:由于这部分知识较为基础,所以我不再在这部分不做更多介绍)
第⼆部分:margin--在同级元素(⾮⽗⼦关系)之间应⽤
  这⼀部分主要介绍⽔平⽅向和竖直⽅向的外边距的合并问题。
 (1)⽔平⽅向的外边距合并
    两个⽔平⽅向的盒⼦相遇,那么最终两者之间的距离为左边盒⼦的右外边距和右边盒⼦的做外边距之和。
    例1:
  代码如下:
display: inline-block;
margin-right: 50px;
font-size: 20px;
}
.right{
width: 100px;
height: 100px;
background: yellow;
display: inline-block;
margin-left: 50px;
font-size: 20px;
}
</style>
</head>
<body>
<div class="left">宽为100px,右边距为50px</div>
<div class="right">宽为100px,左边距为50px</div>
</body>
</html>
效果如下:
这时两者之间的距离刚好为100px。
  补充说明:⼤家可以看到,为了使得两个div(块状元素)脱离正常的⽂档流我使⽤了display:inline-block;属性,另外,我还把body的font-size设置为0,这样可以解决inline-block⾃⾝的问题(如果不清楚这⾥的描述可以看我的博⽂《》,这篇⽂章介绍了inline-block存在的问题),否则两个div的举例会⼤于100px。当然使⽤float也可以使得两个div出现在同⼀⾏中。
  (2)竖直⽅向的外边距合并
  两个竖直⽅向的盒⼦相遇时,其竖直⽅向的距离等于上⽅盒⼦的下外边距和下⽅盒⼦的上外边距中较⼤的⼀个。
  例2:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>⽔平⽅向的两个盒⼦</title>
<style>
*{
margin:0;
padding:0;
border:0;
}
.top{
width: 100px;
height: 100px;
margin-bottom: 100px;
background: red;
}
.bottom{
width: 100px;
height: 100px;
margin-top: 50px;
background: green;
}
</style>
</head>
<body>
<div class="top">⾼为100px,下边距为100px</div>
<div class="bottom">⾼为100px,上边距为50px</div>
</body>
</html>
 效果如下:
这时我们⾁眼都可以观察出来,两者竖直⽅向的举例⼤约为100px(实际就是100px)⽽⾮100+50=150px;这正是因为两个竖直⽅向的盒⼦相遇时,其竖直⽅向的距离等于上⽅盒⼦的下外边距和下⽅盒⼦的上外边距中较⼤的⼀个。
  另外⼀个有趣的例⼦就是:假设有⼀个元素同时设置了margin-top和margin-bottom,但是内容为空,那么这两个margin值也会叠加,值为两者最⼤的⼀个,它类似与竖直⽅向上两个盒⼦margin值的叠加。代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>⽔平⽅向的两个盒⼦</title>
<style>
*{
margin:0;
padding:0;
}
.top{
width: 500px;
height: 100px;
background: red;
}
.middle{
margin-top: 100px;
margin-bottom:50px;
}
.footer{
width: 500px;
height: 100px;
background: green;
}
</style>
</head>
<body>
<div class="top">上⾯的div,⾼100px</div>
<div class="middle"></div>
<div class="footer">下⾯的div,⾼100px</div>
</body>
</html>
最终的效果如下:
  我们发现这时在上⾯的div和在下⾯的div之间的举例并不是100+50=150px,⽽是两者中的最⼤者,即100px。
  那么W3C为什么会设定这样的标准⽽不设定和⽔平⽅向⼀样的标准呢?即margin值的叠加,实际上这也是有⼀定的道理的。⽐如我们需要设计⼀个由若⼲个段落构成的⼀个页⾯。我们需要设置margin-top和margin-bottom使得第⼀段和页⾯的最上⽅有⼀段距离,使得最后⼀段和最下⽅有⼀段距离。下⾯是不叠加和叠加的效果图:
我们可以看到左边的页⾯没有重叠,那么两个段落之间的举例就是最上⽅的两倍间距了,⽽右边的页⾯发⽣了重叠,则所有的间距都是相等的。或许这就是这样设定标准的⽬的吧,谁知道呢?
第三部分:margin--在⽗元素和⼦元素之间应⽤(重点)
 第⼆部分介绍了同级元素之间使⽤margin,⽽这⼀部分将要介绍最有意思的⽗元素和⼦元素之间margin的应⽤。这⼀部分,我们同样从两个⽅⾯来讨论。⼀⽅⾯是⼦元素设置⽔平⽅向上的margin值,另⼀⽅⾯是⼦元素设置竖直⽅向的margin值。
  (1)在⼦元素中设置⽔平⽅向的margin值
   我们可以设置margin-left来控制⼦元素的左边框和⽗元素的左边框之间的举例。
   例3:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>margin</title>
<style>
*{padding:0; margin:0; border:0;}
.father{
width: 500px;
height: 500px;
background: red;
}
.son{
width: 100px;
height: 100px;
background: green;
margin-left: 100px;
}
</style>
</head>
<body>
<div class="father">
<div class="son">宽度为100px,margin-left为100px。</div>
</div>
</body>
</html>
 我将⼦元素的margin-left设置为了100px;效果如下:
即⼦元素的左边框和⽗元素的左边框之间的距离为100px。与在同级元素之间设置margin不同,因为同级元素之间的margin不会考虑到padding,但是在⽗元素和⼦元素就不同了,那么如果⽗元素中如果有padding,效果会是什么样的呢?请看下⾯⼀个例⼦:
  例4:
  下⾯我们在上⾯例⼦的基础上给⽗元素添加padding值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>margin</title>
<style>
*{padding:0; margin:0; border:0;}
.father{
width: 500px;
height: 500px;
padding:100px;
background: red;
}
.son{
width: 100px;
height: 100px;
background: green;
margin-left: 100px;
}
</style>
</head>
<body>
<div class="father">
<div class="son">宽度为100px,margin-left为100px。</div>
</div>
</body>
</html>
上⾯的代码给⽗元素添加了100px的padding值,效果如下:
我们可以看到⼦元素举例上⽅的距离为100px,因为⼦元素⼀定是在⽗元素的content的部分的,这点毫⽆疑问。
但是经过测量可以发现⼦元素的左边框距离⽗元素的左边框之间的距离为200px,因为其中还有100px的左padding值,前⾯的例⼦因为我没有设置padding值,所以没有观察出来,因此这就说明了在⼦元素中设置margin-left,其值实际上是⼦元素的左边框距离⽗元素左padding内侧的距离。
 例5:margin-right的使⽤和margin-left的使⽤是相似的,我在这⾥只举⼀个例⼦。
  这个例⼦在⼦元素中设置了margin-right值,如下所⽰:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>margin</title>
<style>
*{padding:0; margin:0; border:0;}
.father{
width: 500px;
height: 500px;
padding:100px;
background: red;
}
.son{
float: right;
width: 100px;
height: 100px;
background: green;
margin-right: 100px;
}
</style>
</head>
<body>
<div class="father">
<div class="son">宽度为100px,margin-right为100px。</div>
</div>
</body>
</html>
这个例⼦与例4的区别仅在与⼦元素的位置不同。效果如下: