CSS——margin

首先要明确以下两点:

1、元素的显示区域是指:border_left + border_right + paddiing_left + paddiing_right + content ;不包括margion;

2、margin只是是元素盒子的外边距。用于处理元素之间间隔的属性。

详见:CSS——盒子模型

一、基准线的概念:

  基准线或者称为参照线,就像物理中学习的相对运动,物体是向左运动、向右运动亦或是静止,取决于参照物。比如对A、B两个物体进行如下判断:

a、以A物体为参照物,判断物体B的运动方向、距离;

b、以B物体为参照物,判断物体A的运动方向、距离;

在CSS中,我们也可以虚构出基准线这样一个概念。所不同的是,在物理中我们可以随时改变参照物;但是在CSS的具体的情况下,基准线却是不可更改的。

众所周知margin包括:margin-top 、margin-right、margin-bottom、margin-left四个,这四个外边距的基准线可以分为两大类:

  • 以外物作为基准线的:margin-top、margin-left,影响的是自己的显示位置;
  • 以自身的border为基准线的:margin-right、margin-bottom,影响的是后面兄弟元素的显示位置;

兄弟元素之间的基准线选择:

首先定义一个概念:元素的显示区域边界。

显示区域的左边界按照以下原则的先后顺序进行确认:

a、有 border_left,则以 border_left 的最左边为显示区域的左边界;

b、有 paddiing_left, 则以 paddiing_left的最左边为显示区域的左边界;

c、以content的最左边为显示区域的左边界;

显示区域的上边界、右边界、下边界与此类似,不在赘述。

明确显示区域的边界之后再来看基准线:

1、margin-top的外物基准线的选择:

a、垂直上面的兄弟元素显示区域的下边界位置;   ???????是没有脱离文档流还是相连时

b、垂直上面无兄弟元素,并且父亲元素有border-top或者padding-top,则为父元素的 content 的上边位置;

c、父元素不符合条件,则以父元素垂直上面的兄弟元素的显示区域的下边界为基准线;

d、依次类推;

2、margin-left的外物基准线的选择:

a、水平左边的兄弟元素显示区域的右边界位置;   

b、水平左边无兄弟元素,则为父元素的 content 的左边位置;

c、如果父元素没有

3、margin-right的自身基准线:以自身显示区域的右边界为基准线;

4、margin-bottom的自身基准线:以自身显示区域的下边界为基准线;

例子如下: 

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <style type="text/css">
            .back{
                background-color:greenyellow;
            }
            .margin{
                margin:  20px;
                border-color:red ;
            }
            .border{
                border: solid red 2px;
            }
        </style>
    </head>
    <body>
        <div id="div_1" class="back border" style="height: 50px;">
        div_1
        </div>
        <div id="div_2" class="back">
            <div id="div_2_1" class="back margin border" >
                我是子元素A
            </div>
            <div id="div_2_2" class="back margin border" >
                我是兄弟元素B
            </div>
            <div id="div_2_3" class="back border" >
                我是兄弟元素C
            </div>
        </div>
    </body>
</html>

效果如下:

1、两块黄绿色之间的白色区域的成因:因为元素A(div_2_1)的父元素div_2 即没有border,也没有padding,导致元素A的基准线变成了div_1。所以元素A与div_1之间有了间隔,而div_2 没有将这段间隔纳入显示区域;

2、为div_2 增加 border 样式,两块黄绿色之间的白色区域会消失:元素A的基准线变成了父元素div_2。间隔的位置存在div_2的border内部,也就是在div_2的显示区域内。而margion是透明的,显示div_2的背景颜色,所以白色消失。 

3、元素C没有设置 margion,但是元素B 的margion:20px,包含了margion-bottom:20px,所以与兄弟元素B之间有间隔;

 

二、margin垂直外边距合并:

 在垂直方向上都有外边距margion的时候,两个margion会合并,并取最大的为两者之间的间隔:
将上面例子中的元素C 设置style属性如下:

<div id="div_2_3" class="back border" style="margin-top: 40px;" >
    我是兄弟元素C
</div>

 

会发现元素B、C之间的间隔变成了40px,而不是60px;

三、margin设置值的正负问题:

对于margion值的正负,表示的意义是截然不同的。以下均以20px大小为例。?????代表了盒子相对于基准线的移动方向:

1、margin-top:

正:自基准线起,向下取20px作为margin-top,盒子位置随即向下移动20px;

负:首先基准线向上移动20px;在新的基准线起向上取20px作为margion-top的区域;盒子位置向上移动20px;

2、margin-left: 正:向右;负:向左;

正:自基准线起,向右取20px作为margin-left,盒子位置随即向右移动20px;

负:首先基准线向左移动20px;在新的基准线起向左取20px作为margin-left的区域;盒子位置向左移动20px;

3、margin-bottom:正:向上;负:向下;

正:自基准线起,向上取20px作为margin-bottom,盒子高度随即向上增大20px;

负:首先基准线向下移动20px;在新的基准线起向下取20px作为margin-bottom的区域;盒子高度随之向下增大20px;

负值新解释:

margion是用于元素之间保持一定间隔的属性。

4、margin-right:正:向左;负:向右;

正:自基准线起,向左取20px作为margin-right,盒子宽度随之向左增大20px;

负:首先基准线向右移动20px;在新的基准线起向右取20px作为margin-right的区域;盒子宽度随之向右增大20px;

 

四、margin对不同元素的作用效果:

1、对于块级元素可以任意设置,均有效果;

2、对于可替换元素如:select、input、object、img、button、label、textarea等元素,由于其基本类似于块级元素,因此也可以设置;

3、对于非可替换内联(行内)元素,只有 margin-left/margin-right 能够起到一定效果。

 

 

 

详细分析

下面引入margin的“参考线”的概念,margin的“参考线”W3C中没有严格的规范,但通过我们的实战可以很轻易的总结出一些规律,怿飞的总结,怿飞也对margin做了详细的探究(但有部分观点本人不作认同):

如上图是一个盒模型(略去内边距),虚线所示即为margin的参考线,讲作margin 移动的基准点可能更好理解,实线所示为border,浅绿色纯色为margin的区域,显然我们可以把margin的参考线分为两类,top 和 left 的参考线属于一类,right 和bottom 的参考线属于另一类,那它们到底各以什么为参考线呢:

  • top 以 containing block 的 content 上边或者垂直上方相连元素 margin 的下边为参考线垂直向下位移;left 以 containing block 的 content 左边或者水平左方相连元素 margin 的右边为参考线水平向右位移。
  • right 以元素本身的 border 右边为参考线水平向右位移;bottom 以元素本身的border 下边为参考线垂直向下位移。

前面的DEMO1中A的margin-right为-50px,按照“right 以元素本身的 border 右边为参考线水平向右位移”的解释,此时A应该以元素本身的border右边向左位移50px才对(负值与正值的位移方向相反),但要注意!上面讲的位移并不是元素本身的位移,而是自身margin四个方向(top\right\bottom\left)的具体位置的位移! 而实际上虽然A未发生位移,但B却向左位移了50px,这又是为何?B的margin默认为0,B的margin-left寻找的左边参考线即为A元素的margin-right的具体位置,而此时A的margin-right的具体位置在哪?见下图:

按照“right 以元素本身的 border 右边为参考线水平向右位移”的规则,这时的margin的right应从图示蓝色线开始位移,如果是正值则向右位移,但现在是负值,于是向左位移,最终绿色的线为A元素margin的right最终的位置,这个位置也将作为它右边紧跟的B元素margin-left的参考线,而DEMO1中B并未设置margin,即margin默认为0,很显然,B元素就出现在绿色线之后,而覆盖上A元素之上则是由于DOM中后面元素比前面元素优先级高的缘故(当然你也可以为A设置”position:relative”而使A覆盖在B之上)。

来看下DEMO2,A并未设置margin则margin默认为0,B设置了margin-left为-50px,B的margin-left是以A的margin的right的位置为参考线,此时A的margin为0,则B的margin-left即以A的右border为参考线开始位移,如果是正值则是向右位移,现在是负值即向左位移,所以最终也会和DEMO1一样呈现出一样的现象:B覆盖于A之上,位移大小为50px。

DEMO3中的关系其实是父子元素的关系,根据前面的“left 以 containing block 的 content 左边向右位移”的规则,A设置了margin-left为-50px,本是正值向右位移,现在是负值,则向左位移50px,参考线是包含块的content左侧,来看下图:

按照“left 以 containing block 的 content 左边向右位移”的规则,这时A的margin的left应从图示蓝色线开始位移,如果是正值则向右位移,但现在是负值,于是向左位移,最终绿 色的线为A元素margin的left最终的位置。

DEMO4其实和DEMO3是一个性质,由于是父元素本身margin的left发生位移,那么它就会依据DEMO3一样继续去找它的包含块的content左侧,发生了左移也是很好理解的,至于其中的A只是混淆视听罢了,在父元素中,A其实是相对于父元素静止的。

通过四个DEMO的分析,并加入参考线的概念后大家是否可以理解了呢?不知道各位有没有这样一个疑问:margin-left的时候元素本身发生了位移,但margin-right为何并没有致使本身发生位移?下面谈谈我个人的理解:

元素之间有个例如DEMO1中的A元素设置了margin-right为-50px,按道理讲应当向右位移50px,但是根据页面排版顺序来讲,必须先渲染左边的元素,渲染完了再渲染右边的元素,那么这时右边元素的位置则依赖于左边的元素,左边元素的margin-right不可能先去找右边元素的参考线,左边元素的margin-right的作用仅仅是提供了右边元素margin-left的参考线。而如果是父子元素的关系,则最左边的子元素的margin-left则依赖于它的包含块。注意了,这里有一个特殊情况,当为元素设置了”float:right”时,元素会脱离布局流,这时如果再为它设定marign-right为-50px时,它本身会发生偏移,因为它依赖于它的包含块。这与怿飞总结的“如果是负的 top 或 left 值会引起 box 的向上或向左位置移动,如果是 bottom 或 right 只会影响下面 box 的显示的参考线”的也是有出入的。

 

http://www.hicss.net/i-know-you-do-not-know-the-negative-margin/

http://www.w3school.com.cn/css/css_margin_collapsing.asp

http://www.planabc.net/2007/03/18/css_attribute_margin/

 

http://www.smallni.com/negative-margin/

http://www.zhihu.com/question/20116963

http://www.hicss.net/do-not-tell-me-you-understand-margin/

http://www.hicss.net/separation-of-powers-model-in-css-design-patterns/

http://www.cnblogs.com/dolphinX/p/4071725.html

posted @ 2015-05-10 16:16  志在天涯  阅读(498)  评论(0编辑  收藏  举报