您好,欢迎来到九壹网。
搜索
您的当前位置:首页深入理解css中的margin属性

深入理解css中的margin属性

来源:九壹网
深⼊理解css中的margin属性

之前我⼀直认为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; }

宽为100px,右边距为50px
宽为100px,左边距为50px

效果如下:

这时两者之间的距离刚好为100px。

  补充说明:⼤家可以看到,为了使得两个div(块状元素)脱离正常的⽂档流我使⽤了display:inline-block;属性,另外,我还把body的font-size设置为0,这样可以解决inline-block⾃⾝的问题(如果不清楚这⾥的描述可以看我的博⽂《》,这篇⽂章介绍了inline-block存在的问题),否则两个div的举例会⼤于100px。当然使⽤float也可以使得两个div出现在同⼀⾏中。

  (2)竖直⽅向的外边距合并

  两个竖直⽅向的盒⼦相遇时,其竖直⽅向的距离等于上⽅盒⼦的下外边距和下⽅盒⼦的上外边距中较⼤的⼀个。  例2:

⽔平⽅向的两个盒⼦

⾼为100px,下边距为100px
⾼为100px,上边距为50px

 效果如下:

这时我们⾁眼都可以观察出来,两者竖直⽅向的举例⼤约为100px(实际就是100px)⽽⾮100+50=150px;这正是因为两个竖直⽅向的盒⼦相遇时,其竖直⽅向的距离等于上⽅盒⼦的下外边距和下⽅盒⼦的上外边距中较⼤的⼀个。  

  另外⼀个有趣的例⼦就是:假设有⼀个元素同时设置了margin-top和margin-bottom,但是内容为空,那么这两个margin值也会叠加,值为两者最⼤的⼀个,它类似与竖直⽅向上两个盒⼦margin值的叠加。代码如下:

⽔平⽅向的两个盒⼦

上⾯的div,⾼100px

下⾯的div,⾼100px

最终的效果如下:

  我们发现这时在上⾯的div和在下⾯的div之间的举例并不是100+50=150px,⽽是两者中的最⼤者,即100px。  

  那么W3C为什么会设定这样的标准⽽不设定和⽔平⽅向⼀样的标准呢?即margin值的叠加,实际上这也是有⼀定的道理的。⽐如我们需要设计⼀个由若⼲个段落构成的⼀个页⾯。我们需要设置margin-top和margin-bottom使得第⼀段和页⾯的最上⽅有⼀段距离,使得最后⼀段和最下⽅有⼀段距离。下⾯是不叠加和叠加的效果图:

我们可以看到左边的页⾯没有重叠,那么两个段落之间的举例就是最上⽅的两倍间距了,⽽右边的页⾯发⽣了重叠,则所有的间距都是相等的。或许这就是这样设定标准的⽬的吧,谁知道呢?

第三部分:margin--在⽗元素和⼦元素之间应⽤(重点)

  第⼆部分介绍了同级元素之间使⽤margin,⽽这⼀部分将要介绍最有意思的⽗元素和⼦元素之间margin的应⽤。这⼀部分,我们同样从两个⽅⾯来讨论。⼀⽅⾯是⼦元素设置⽔平⽅向上的margin值,另⼀⽅⾯是⼦元素设置竖直⽅向的margin值。

  (1)在⼦元素中设置⽔平⽅向的margin值

    我们可以设置margin-left来控制⼦元素的左边框和⽗元素的左边框之间的举例。    例3:

margin

宽度为100px,margin-left为100px。

 我将⼦元素的margin-left设置为了100px;效果如下:

即⼦元素的左边框和⽗元素的左边框之间的距离为100px。与在同级元素之间设置margin不同,因为同级元素之间的margin不会考虑到padding,但是在⽗元素和⼦元素就不同了,那么如果⽗元素中如果有padding,效果会是什么样的呢?请看下⾯⼀个例⼦:    例4:

  下⾯我们在上⾯例⼦的基础上给⽗元素添加padding值。

margin

宽度为100px,margin-left为100px。

上⾯的代码给⽗元素添加了100px的padding值,效果如下:

我们可以看到⼦元素举例上⽅的距离为100px,因为⼦元素⼀定是在⽗元素的content的部分的,这点毫⽆疑问。

但是经过测量可以发现⼦元素的左边框距离⽗元素的左边框之间的距离为200px,因为其中还有100px的左padding值,前⾯的例⼦因为我没有设置padding值,所以没有观察出来,因此这就说明了在⼦元素中设置margin-left,其值实际上是⼦元素的左边框距离⽗元素左padding内侧的距离。

 例5:margin-right的使⽤和margin-left的使⽤是相似的,我在这⾥只举⼀个例⼦。  这个例⼦在⼦元素中设置了margin-right值,如下所⽰:

margin

宽度为100px,margin-right为100px。

这个例⼦与例4的区别仅在与⼦元素的位置不同。效果如下:

通过这个例⼦可以说明margin-right的值是⼦元素的右边框和⽗元素的右padding内侧的距离。只是前⾯的⼏个例⼦我没有使⽤padding,所以⽆法观察出来。

  (2)在⼦元素中设置竖直⽅向的margin值

    按照前⾯的经验,理论上来说,我们同样可以通过设置margin-top的值使得⼦元素的上边框和⽗元素的上padding的内侧留有⼀定的距离。那么我们就试试吧!  例6:

margin

⾼度为100px,margin-top为100px。

 这个例⼦我设置了margin-top为100px,效果如下:

这并不是我们想要的效果啊,我们希望⼦元素的上部距离⽗元素的上部为100px,可是我们看到的却是⽗元素的上部距离浏览器页⾯的上部有100px的距离,这是为什么呢?哪⾥出现问题了呢?  

  实际上这是因为当⽗元素没有设置padding值以及border值时,出现了⼀个bug--⽗元素的上⽅与⼦元素的上⽅完全重合在了⼀起,⽆法分开。所以才会导致上述这种⽗元素和⼦元素同时向下的情况。  对于这种问题解决⽅法有下⾯⼏种:

⽅法⼀:给⽗元素添加padding-top值⽅法⼆:给⽗元素添加border值

⽅法三:给⽗元素添加属性overflow:hidden;⽅法四:给⽗元素或者⼦元素声明浮动float

⽅法五:使⽗元素或⼦元素声明为绝对定位:position:absolute;

⽅法六:给⽗元素添加属性 overflow:auto; positon:relative;(注:此⽅法为后续添加,感谢博友@⼩精灵Pawn提供此⽅法)  ⽅法⼀:基于例6,在⽗元素的css代码中添加padding-top:1px;效果如下:

⽅法的唯⼀缺点就是增加了1px的误差。  

  ⽅法⼆:基于例6,在⽗元素的css代码中添加border-top:1px solid transparent;效果如下:

同样达到了效果, 缺点同⽅法⼀。  

  ⽅法三:基于例6,在⽗元素的css代码中添加overflow:hidden;效果如下:

 

同样达到了效果,并且没有任何误差的存在。堪称perfect  

  ⽅法四:给⽗元素或者⼦元素声明float;基于例6,在⼦元素css代码添加float:left;或者在⽗元素css代码添加float:left;均达到效果,这⾥不再展⽰相同的图⽚。    优点:没有像素的误差。 缺点:float有时是不必要的。

  ⽅法五:给⽗元素或者⼦元素添加position:absolute;属性。 同样达到效果。

    优点:同⽅法四。 且只要我们不使⽤top和left也不会有任何影响,所以这也是⼀种不错的⽅法。

(说明:博友 @laden666666 指出,上述⽅法三、四、五实际上都是去除⼦元素margin穿透⽗容器的⽅法,可以归类为bfc法,本质相同。 在此表⽰感谢) ⽅法六:给⽗元素添加overflow:auto;和position:relative;同样达到效果。     此⽅法亲测有效,是博友 @⼩精灵Pawn提供,在此表⽰感谢。

第四部分:margin值的单位为%时的⼏种情况

    之前我举例⼦时使⽤margin,它的值都是以px为单位的,这个理解起来没有问题。但是如果margin值是以%为单位呢?实际上这时候百分⽐(%)是相对于该元素的⽗元素(容器),对于同级元素和⽗⼦元素都是如此。(再次感谢 博友@⼩精灵Pawn 提供的建议!!基于此建议补充这部分内容) 但是在同级元素中使⽤竖直⽅向的margin时会出现意想不到的结果,下⾯举例说明。

  (1)同级元素在⽔平⽅向使⽤值为%的margin

  例7:

margin

宽为200,⽆margin

宽为200,margin-left为20%;

这个例⼦中,设置两个元素向左浮动,以便于观察两者⽔平⽅向的margin。其中左边div⽆margin,右边div的margin-left为20%,效果如下:

从效果图可以看出两个div之间的间距始终为⽗元素(这⾥右边div的⽗元素即为body,其宽度为浏览器宽度)的20%。    

  (2)同级元素在竖直⽅向使⽤值为%的margin

   根据例7的启发,我们可以猜想,如果在竖直⽅向上使⽤margin,且值的单位为%,那么最终两者之间的距离将是⽗元素(上例中为body)的百分数。那么究竟是不是这样呢?看下⾯的例⼦。例8

margin

⾼为200,⽆margin

⾼为200,margin-top为20%;

这⾥设置上⾯的div⽆margin,下⾯的div的margin-top为10。效果如下:

我们发现,当我在缩⼩浏览器的⾼度时,竖直⽅向上的间距并没有缩⼩ ⽽当我缩⼩浏览器的宽度时,竖直⽅向上的距离缩⼩了这就说明:统计元素之间在竖直⽅向上使⽤margin,当值的单位为%时,它是相对于⽗元素的宽度。

 

  (3)⽗⼦元素使⽤值为%的margin

    对于⽗⼦元素,如果在⼦元素中使⽤单位为%margin,那么这个margin值是相对于⽗元素的宽度和⾼度(注意:这时的确是相对于⽗元素的⾼度!)的。   例9     代码如下:

Document

在这个例⼦中,我设置了margin-left的值为20%,margin-top的值为20%,⽗元素的width为500px,⽗元素的height为300px。下⾯看看效果吧。

从上图可以看出⼦元素的margin-top值最终同样是相对与⽗元素的宽度⽽⾮⾼度。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 91gzw.com 版权所有 湘ICP备2023023988号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务