注:本文个别观点仅是个人衍生的一些想法,仅供参考。

 margin是一个说起来,看起来都很简单但是玩起来并没有那么简单的东西。本文不会对margin的各种常见问题做分析,比如常见的外边距合并等等,只会单独的来说一说对于margin负值的理解。

margin一共有4个方向上的取值,按照css中的赋值顺序来就是:top right bottom left。四个值可以取正数,表现形式为4个方向上的外边距扩散。同时他们也可以取负值。但是在不同的‘流’中,表现形式会有所差异。本文只探讨普通流中的表现。 在定位和浮动中表现大同小异。

 

 

我们先来看一个小demo

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>test</title>
    <style>
        .wrapper {
            border: 1px solid red;
            margin-top: 150px;
        }

        .wrapper div {
            height: 50px;
            width: 100px;
            display: inline-block;
            border: 1px solid #000;
        }

        .wrapper div:nth-of-type(1) {
            background-color: deeppink;
        }

        .wrapper div:nth-of-type(2) {
            background-color: #ffac00;
        }

        .wrapper div:nth-of-type(3) {
            background-color: #ac589a;
        }
    </style>
</head>

<body>
    <div class="wrapper">
        <div>1</div>
        <div>2</div>
        <div>3</div>
    </div>
</body>

</html>

效果图如下

android margininTop 为负数 margin值为负_html

margin-top:30px 与 margin-top:-30px 比较

android margininTop 为负数 margin值为负_css_02

30px 

android margininTop 为负数 margin值为负_css_03

-30px

这里要注意一个点就是要在margin-top:-30px下看到效果需要设置vertical-align:top或者删除文字,具体原因这篇文章写得很好。

margin-bottom:30px 与 margin-bottom:-30px 比较

android margininTop 为负数 margin值为负_取值_04

30px 

android margininTop 为负数 margin值为负_margin_05

-30px

margin-left:30px 与 margin-left:-30px 比较

android margininTop 为负数 margin值为负_css_06

30px 

android margininTop 为负数 margin值为负_html_07

-30px

margin-right:30px 与 margin-right:-30px 比较

android margininTop 为负数 margin值为负_取值_08

30px 

android margininTop 为负数 margin值为负_负值_09

-30px

在看了不同取值情况下不同的表现后,可能有的同学会豁然开朗,也可能会感到迷惑,接下来对此分析分析。

其实你看的足够仔细的话应该可以发现,1.它们都产生了层级关系(上下可以通过改成块级元素看出),2.top和left是同一种表现,right和bottom是同一种表现。前者就是按照自己相反的方向位移相同的距离,而后者则像是把自己同方向上的兄弟元素往自己身边拉相同的距离。产生这种差异的原因主要是,top和left的位移是参考外元素来移动自己,而right和bottom是把自己作为了参考物来影响它周围的元素,如果你对这句话很疑惑的话,可以去看看(containing block)的相关知识。

如果再说的浅显一点可以分为两种理解方式

1.参考线理解。引用网上的一句话“在margin属性中一共有两类参考线,top和left的参考线属于一类,right和bottom的参考线属于另一类。top和left是以外元素为参考,right和bottom是以元素本身为参考。”我们可以想象父元素Wrapper的border就是那条参考线,当取值为正负的时候,第一个元素的top和left就正反方向位移相应的距离,同样第二个元素是以他前面那个元素的border作为参考线。而取值为bottom和right的时候,元素自己本身成为了参考物来影响它周围的元素,正值道理相同,在负值的时候,可以想象它自己内凹了一段距离,同样带动参考线内凹了,所以其后面的元素也就跟着这条参考线跑了过去,看起来就像是被吸了回去。这样的说法并不严谨,因为W3C并没有参考线的说法,但是我觉得有助于理解。

2.盒子模型理解。了解过盒子模型的同学都知道,在标准盒模型下,元素的width = border-left+border-right+padding-left+padding-right+contentWidth+margin-left+margin-right。高度同理。所以我们可以这样理解,因为文档流只能向左或向上流动,不能向下或向右流动。所以当取值为right和lbottom的时候,因为外边距取了负数,所以只能通过减少自身内容区的高度或者宽度来满足盒子模型的等式,所以后面的元素因为‘流’的特点就占据了它原来的位置,但是元素的高度并不是真的减少了,只是供给css可读的高度减少了。而取值为left和top时,道理相同,因为自己的那部分高度或者宽度减少了,自然而然的就流向了前面或者上面。另外还有一点,当元素被包裹在一个父容器中,如果没有设置宽度。使用left或者right为负数,它的宽度就会增加,这一点也可以通过盒模型来理解。因为要满足等式,只能增加自身宽度。