一起来探索CSS中margin属性的奥秘吧!!
作者:
WangMin
格言:努力做好自己喜欢的每一件事
众所周知 margin属性
是用来声明当前所设置或者指定元素所有外边距的宽度,或者设置各边上外边距的宽度。一直以来我认为它是一个很简单的属性,但是在最近的所做的项目中我遇到了一些关于 margin属性
所涉及到的问题,下面就给大家分享一下吧!!
margin 属性的简单概述
说到 margin 属性
,就必须先了解 css盒子模型(Box Model)
,因为css盒子模型是用来设计和布局的,本质来讲是一个盒子,下面是 css盒子模型(Box Model)
的图例,如下:
从上图中可以看到 css盒子模型(Box Model)
包括:外边距(margin)
、边框(border)、内边距(padding)以及最中间的内容(content),其中就包含我所要讲的 外边距(margin)
,它处于盒子模型的最外层,也就是上图中显示 margin字样
的那一层,它可以用来使不同的盒子之间留有一定的间隔从而达到布局整洁美观的效果。
从上图中的 css盒子模型(Box Model)
中可以看到margin在上下左右四个方向都存在,也就是说我们可以使用margin-top(上外边距)
、margin-right(右外边距)
、margin-bottom(下外边距)
、margin-left(左外边距)
分别设置这四个方向的margin值。这是margin 属性
最基本的用法,相信大家运用的很熟练了吧!!
margin 属性的使用语法
上面也提到了margin在上下左右四个方向都存在,可使用margin-top(上外边距)
、margin-right(右外边距)
、margin-bottom(下外边距)
、margin-left(左外边距)
分别设置这四个方向的margin值,案例1如下:
<div id="outer">
<div id="inner"></div>
</div>
#outer{
width:90px;
height:150px;
margin: 10px auto;
border:1px solid #ccc;
}
#inner{
width:50px;
height:50px;
margin-top:20px;
margin-bottom:20px;
margin-left:20px;
margin-right:20px;
background:#000;
}
网页效果如下:
所对应的盒子模型如下:
上面的例子中我是分别给元素#outer
添加了四个方向的外边距,并且外边距都相等,这样会让css在渲染的时候时间加长,并且程序性能降低,所以避免这种情况,我们可以把它简写为以下格式,所得到的效果是一样的。
#outer{
width:100px;
height:100px;
margin:20px;
background: #f00;
}
那么可能就有人会问了,如果四个方向的外边距不一样该怎么来设置呢?当然你可以用上边的提到的分别为四个方向设置相对应的外边距,也可以利用简写的方式来设置,效果其实是一样的,案例2如下:
<div id="outer">
<div id="inner"></div>
</div>
#outer{
width:150px;
height:150px;
margin: 10px auto;
border:1px solid #ccc;
}
#inner{
width:50px;
height:50px;
margin:20px 30px 40px 50px;
background:#000;
}
网页效果:
所对应的盒子模型如下:
那么在使用margin属性简写形式应该注意的点如下:
1、如果提供全部四个参数值,第一个参数表示上外边距,第二个参数表示右外边距,第三个参数表示下外边距,第四个参数表示左外边距
。如案例2。
2、如果只提供一个参数值,这一个参数值则表示四个方向的外边距。也就是说四个方向的外边距是相等的
。 如案例1中的简写形式。
3、如果提供两个参数值,第一个则表示上、下两边的外边距,第二个则表示左、右两边的外边距。 也就是说上、下两边的外边距相等,左、右两边的外边距相等
。案例3如下:
<div id="outer">
<div id="inner"></div>
</div>
#outer{
width:110px;
height:150px;
margin: 10px auto;
border:1px solid #ccc;
}
#inner{
width:50px;
height:50px;
margin:20px 30px;
background:#000;
}
网页效果如下:
所对应的盒子模型如下:
4、如果提供三个,第一个则表示上外边距,第二个则表示左、右两边的外边距,也就说左右两边的外边距相等,第三个则表示下外边距。 案例4如下:
<div id="outer">
<div id="inner"></div>
</div>
#outer{
width:110px;
height:150px;
margin: 10px auto;
border:1px solid #ccc;
}
#inner{
width:50px;
height:50px;
margin:20px 30px 10px;
background:#000;
}
网页效果如下:
所对应的盒子模型如下:
margin外边距合并(重叠)的问题
在使用CSS的margin属性时,会出现margin属性垂直外边距的合并(折叠)的现象。这种合并(重叠)现象分为两种: 兄弟元素的合并
和 嵌套元素的合并
。
先来了解什么是垂直外边距?margin-bottom 和 margin-top就是垂直外边距
1、兄弟元素垂直外边距的合并
素垂直外边距重叠要满足三个重要的原因:1) 相邻的元素 ; 2)他们都设置得有垂直的外边距; 3) 在上一个兄弟节点的外边距设置为:margin-bottom,并且下一个兄弟节点的外边距设置为:margin-top的情况下,才会出现垂直外边距重叠的情况。
案例6如下:
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
.box{
width:100px;
height:100px;
}
#box1{
background:#f00;
margin-bottom: 20px;
}
#box2{
background:#000;
margin-top: 30px;
}
网页效果如下:
从图中可以看出给box1设置的margin-bottom: 20px的下外边距 和 box2设置的margin-top: 30px的上外边距 , 他们两个的外边距并没有求和累加为50px,而是重叠了合并为30px。这是因为 当两个元素为兄弟元素时,两者相隔的外边距,取的是两者所设置垂直margin的最大值
。
那么如果给box1的margin-bottom和box2的margin-top都设置为20px,那会是怎样的效果呢?效果如下:
从上图可以看出他们两个的外边距并没有求和累加为40px,而是重叠了合并为20px。这是因为 如果相邻的两个外边距值相等,那么就取这个相等的值作为外边距
。
如何解决垂直外边距重叠问题呢?假如有的时候不想让垂直外边距重叠, 应该怎么办呢? 这个问题就要说回到他们为什么重叠,就是因为他们彼此是相邻的兄弟元素
! 那么我们可以让他们 不相邻 不就解决了这个问题了吗! 比如: 我们在他们彼此相邻元素之间加入一些字符,换句话说 用一些字符或者其他元素来隔开相邻的兄弟元素,那么他们彼此之间就不会产生外边距重叠的问题了
。案例7如下:
<div id="box1" class="box">box1</div>
<span id="line"></span>
<div id="box2" class="box">box2</div>
.box{
width:100px;
height:100px;
color:#fff;
}
#box1{
background:#f00;
margin-bottom: 20px;
}
#box2{
background:#000;
margin-top: 30px;
}
#line{
width:100px;
height:1px;
display: block;
}
网页效果如下:
从上图中我们可以看见 中间的 span元素
的确起到了隔离他们,并且让他们的外边距无法再重叠!
案例6与案例7中margin的垂直外边距都为正数,那么如果其中一个元素的margin垂直外边距为负的情况下,该怎样来计算它们的垂直外边距呢? 如下:
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
.box{
width:100px;
height:100px;
}
#box1{
background:#000;
margin-bottom: -20px;
}
#box2{
background:#ccc;
margin-top:30px;
}
网页效果如下:
从案例中可以看出两个元素的垂直外边距只有10px,是怎样计算出这10px的呢?如果相邻元素的 margin 中有正值,同时存在负值,先取出负 margin 值和正 margin 值相加就可以了
。所以上述案例中最终所得到的垂直外边距为-20px+30px=10px。
那么如果两个元素的margin垂直外边距都为负的情况下,该怎样来计算它们的垂直外边距呢? 如下:
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
.box{
width:100px;
height:100px;
}
#box1{
background:#000;
margin-bottom: -20px;
}
#box2{
background:#ccc;
margin-top:-50px;
margin-left:10px;
}
网页效果如下:
从上图中可以看出在元素box1与元素box2的margin垂直外边距都为负的情况下,最终它们的垂直外边距取得竟然是元素box2的margin-top的值,也就是元素box2向上移动了50px,覆盖住了元素box1。
由此可以得出一个结论:当 两个元素的margin 都是负值的时候,取的是其中绝对值较大的,然后从 0 位置,负向位移相应的距离。
2、嵌套元素的合并
当两个元素嵌套到一起,也就是一个父元素中嵌套了一个子元素,并且子元素设置了一个margin-top属性,这个时候如果没有内边距或边框把外边距分隔开时,它们的外边距也会发生合并。案例8如下:
<div id="box1" >
<div id="box2"></div>
</div>
#box1{
width:200px;
height:200px;
background:#f00;
}
#box2{
width:100px;
height:100px;
background:#000;
margin-top:20px;
}
网页效果如下:
从上图可以看到 父元素box1往下移动了20px 但其实我认为是子元素box2所产生的margin-top:20px外边距把 父元素box1挤下来了! 但是我要的效果并不是这样的,我只想让子元素box2的上外边距与 父元素box1有20px的距离,效果如下:
上面也提到了如果没有内边距或边框把外边距分隔开时,它们的外边距就会发生合并,那么如果给父元素设置一个边框属性将父元素与子元素分隔开时,就可以实现我想要的效果了,代码如下:
#box1{
width:200px;
height:200px;
border:1px solid #ccc;
background:#f00;
}
除了这种方案,其实解决这个问题的方法还有很多! 比如给父元素添加overflow:hidden、给父元素中加内容,给父元素设置padding
等等。但给父元素加border 或 padding 这些属性会改变父元素的可见宽高度,并不是最佳解决方案!所以 推荐使用给父元素添加overflow:hidden来解决嵌套元素的垂直外边距合并的问题
。
3、 margin水平外边距合并问题
先来了解什么是水平外边距? 也就是margin-left和margin-right !
两个水平方向的元素,那么最终两者之间的距离为左边盒子的右外边距和右边盒子的做外边距之和,它们之间不存在外边距合并问题。案例9如下:
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
.box{
width:100px;
height:100px;
float: left;
}
#box1{
background:#f00;
margin-right: 20px;
}
#box2{
background:#000;
margin-left: 30px;
}
网页效果如下:
margin值的单位为%百分比时
以上我举例子时使用margin,它的值都是以px为单位的,这个理解起来很简单。但是如果margin值是以%为单位呢?实际上这时候百分比(%)是相对于该元素的父元素(容器),对于同级元素和父子元素都是这样。
1、同级(兄弟)元素在水平方向使用值为%的margin,案例10如下:
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
.box{
width:100px;
height:100px;
float: left;
}
#box1{
background:#f00;
}
#box2{
background:#000;
margin-left: 10%;
}
这个例子中,两个元素都设置向左浮动,可以很清楚的看到两者水平方向的margin。其中元素box1没有设置margin,元素box2的margin-left为10%,网页效果如下:
从上图中可以看出两个div之间的间距是父元素宽度(这里的因为两个div没有被外部元素直接包裹住,所以会直接找到根元素body,父元素宽度就是指浏览器的宽度)的10%。可以通过改变浏览器的宽度来观察margin-left值的变化。
2、同级(兄弟)元素在竖直方向使用值为%的margin
上面也讲到同级(兄弟)元素在水平方向设置值为%的margin时,是相对于父元素的宽度,那么(兄弟)元素在垂直方向设置值为%的margin时,会不会相对于父元素的高度呢?案例11如下:
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
.box{
width:100px;
height:100px;
}
#box1{
background:#f00;
}
#box2{
background:#000;
margin-top: 10%;
}
这个例子中,元素box1没有设置margin,元素box2的margin-top为10%,网页效果如下:
我们可以发现当我们缩小浏览器的高度时,元素box2竖直方向上的外间距并没有相对于浏览器的高度的改变而改变,但是当改变浏览器的宽度时,元素box2竖直方向上的外间距反而随之改变。所以可以的出一个结论:元素之间在竖直方向上使用margin,当值的单位为%时,它也是相对于父元素的宽度
。
3、嵌套(父子)元素使用值为%的margin
对于嵌套(父子)元素,如果在子元素中使用单位为%的margin,那么这个margin值是相对于父元素的宽度和高度,案例12如下:
<div id="box1" >
<div id="box2"></div>
</div>
#box1{
width:300px;
height:200px;
background:#f00;
overflow: hidden;
}
#box2{
width:100px;
height:100px;
background:#000;
margin-left: 10%;
margin-top:10%;
}
这个例子中,父元素box1没有设置margin,子元素box2的margin-left为10%,margin-top为10%,那么根据父元素的宽度来计算子元素box2的margin-left值就是300*10%=30px,根据父元素的高度来计算子元素box2的margin-top值就是200*10%=20px,网页效果如下:
子元素box2所对应的盒子模型如下:
从上图中我们可以看出子元素box2的margin-top与margin-left都为30px,而不是上面我们计算出来200*10%=20px,这说明 子元素的margin-top值最终同样是相对与父元素的宽度而不是高度
。
margin为负值
margin外边距属性的值 是可以支持 负值的 ,如果设置负值,则元素会向反方向移动!
1、当给一个元素设置负的margin-left值时,案例13如下:
<div id="box1" >
<div id="box2"></div>
</div>
#box1{
width:300px;
height:200px;
background:#f00;
margin:0 auto;
}
#box2{
width:100px;
height:100px;
background:#000;
margin-left: -20px;
}
网页效果如下:
子元素box2所对应的盒子模型如下:
从上图中我们可以看到子元素box2移出了父元素的左边20px。
2、当给一个元素设置负的margin-top值时,案例14如下:
<div id="box1" >
<div id="box2"></div>
</div>
#box1{
width:300px;
height:200px;
background:#f00;
margin:0 auto;
}
#box2{
width:100px;
height:100px;
background:#000;
margin-top: -20px;
}
网页效果如下:
子元素box2所对应的盒子模型如下:
从上图中我们可以看到子元素box2移出了父元素的顶部20px。
从上面两个例子中可以得出一个结论:当给一个元素设置margin-left和margin-top为负值时,元素就会向该方向移动相应的距离
3、当给一个元素设置负的margin-right值时,案例15如下:
<div id="box1" >
<div id="box2" class="box"></div>
<div id="box3" class="box"></div>
<span>我是一个span</span>
</div>
#box1{
width:300px;
height:200px;
background:#f00;
color:#fff;
margin:20px auto;
}
.box{
width:100px;
height:100px;
float: left;
}
#box2{
background:#000;
margin-right: -20px;
}
#box3{
background:#ccc;
}
网页效果如下:
从上图中可以看出元素box1并没有发生改变,反而同级元素box2会向左移动20px并且覆盖了元素box1。
4、当给一个元素设置负的margin-bottom值时,案例16如下:
<div id="box1" >
<div id="box2" class="box"></div>
<div id="box3" class="box"></div>
<span>我是一个span</span>
</div>
#box1{
width:300px;
height:200px;
background:#f00;
color:#fff;
margin:20px auto;
}
.box{
width:100px;
height:100px;
}
#box2{
background:#000;
margin-bottom: -20px;
}
#box3{
background:#ccc;
}
网页效果如下:
从上图中可以看出元素box1并没有发生改变,反而同级元素box2会向上移动20px并且覆盖了元素box1。
从上面案例15、16两个例子中可以得出一个结论:当给一个元素设置margin-right和margin-bottom为负值时,元素的位置不会相对于父元素发生任何改变,但是后面的元素会产生相同方向的位移,并覆盖自己
。
利用margin实现元素居中效果
可以利用margin-right 和 margin-left同时设置auto来实现元素居中效果。那么它的实现原理是怎样的呢?
原理如下:如果两个水平方向都设置auto,则会将两侧的外边距设置为相同的左右外边距最大值! 也就是 浏览器会将父元素的宽度减去需要居中的元素的宽度过后剩余空间的宽度分为相等的两份分别作为需要居中的元素的左右外边距
。这样一来就可以使元素自动在父元素中 水平居中了! 这个技巧也是我们经常会使用到的。
所以我通常会简写为: margin 0 auto; 对元素进行水平居中,案例17如下:
<div id="box1" >
<div id="box2"></div>
</div>
#box1{
width:300px;
height:200px;
background:#f00;
overflow: hidden;
}
#box2{
width:100px;
height:100px;
background:#000;
margin:0 auto;
}
给box2设置了 margin:0 auto,网页效果如下:
子元素box2所对应的盒子模型如下:
从上图中可以看出子元素box2的margin-left与margin-right都为100px,是怎么得到的呢?根据上面利用margin实现居中的原理,利用 父元素的宽度-子元素的宽度/2
得到的值分别给子元素box2的margin-left与margin-right,就是(300px-100px)/2=100px。
使用margin属性无效的元素
行内元素垂直
margin (margin-top、margin-bottom)值不起作用。也就是说,普通的行内元素是无法使用垂直 margin (margin-top、margin-bottom)
的。但是行内元素水平
margin(margin-left、margin-right)是有效的。案例18如下:
<div id="outer">
<span id="inner">inner</span>
</div>
#outer{
width:110px;
height:150px;
margin: 10px auto;
border:1px solid #ccc;
}
#inner{
color:#fff;
margin:20px 10px 10px;
background:#000;
}
网页效果如下:
以上仅是个人见解,若有不足之处欢迎在下方评论指出,那就先分享到这里!! 😄 后续继续更新!!