负margin技术原理与运用 | CSS

1,910 阅读4分钟

在CSS中,margin的值可以是正数,也可以是负数。
当margin为负数的时候,对普通文档流元素和对浮动元素的影响是不一样的。

margin的两种情况

  1. 当元素的margin-top或者margin-left为负数时,“当前元素”会被拉向指定方向。
  2. 当元素的margin-bottom或者margin-right为负数时,“后续元素”会被拉向指定方向。

我们来看看下面的例子:

<style>
  .container div {
    width: 300px;
    height: 60px;
    line-height: 60px;
    text-align: center;
    color: #fff;
  }
  .first { background-color: red; }
  .second { background-color: purple; }
  .third { background-color: blue; }
</style>
<div class="container">
  <div class="first">1</div>
  <div class="second">2</div>
  <div class="third">3</div>
</div>

未设置margin的情况

margin-topmargin-left举例

当元素的margin-top或者margin-left为负数时,“当前元素”会被拉向指定方向。

此时我们将第2个div的margin-top进行设置:.second { margin-top: -30px; },效果如下:

第2个div设置margin-top为-30px

可以看到,当前元素(第2个div)被拉向top方向30px,并且覆盖了div1。

如果是margin-left同理(可以理解为上图逆时针旋转90°),将第2个div设置为:.second { margin-left: -30px; },效果如下:

第2个div设置margin-left为-30px

当前元素(第2个div)被拉向tleft方向30px,并且覆盖了div1。

margin-bottommargin-right举例

当元素的margin-bottom或者margin-right为负数时,“后续元素”会被拉向指定方向。

我们试着将第2个div的margin-bottom进行设置:.second { margin-bottom: -30px; },效果如下:

第2个div设置margin-bottom为-30px

可以看到后续元素(即第2个div)被拉向上一个元素(即第2个div)的方向,且覆盖了上一个元素。 margin-right也一样:

第2个div设置margin-right为-30px

运用场景

了解了负margin的规则,我们来聊聊具体使用的场景。
比较常用的技巧有:

  1. 图片与文字对齐
  2. 自适应两列布局
  3. 元素垂直居中
  4. tab选项卡

图片与文字对齐

当图片与文字排在一起的时候,在底部水平方向上往往都是不对齐的。如:

<img src="./icon.png" alt="icon">这是一个图标

底部没有对齐

这是因为,图片与文字默认是基线对齐(vertical-align:baseline;)。

如果想要实现图片与文字底部水平方向对齐,除了使用vertical-align:text-bottom;这个方法之外,还可以使用兼容性比较好的负margin来实现:margin-bottom: -3px;,效果如下:

margin-bottom: -3px;

这个3px正是文本中baselinebottom的距离。

自适应两列布局

自适应两列布局通常指的是一列宽度固定,另一列宽度自适应的布局方式。利用负margin技术可以很好地实现这种布局。

<style>
  div {
    float: left;
    color: #fff;
    height: 500px;
  }
  .siderBar {
    width: 200px;
    background-color: purple;
  }
  .content {
    width: 100%;
    margin-right: -200px;
    background-color: plum;
  }
</style>
<body>
    <div class="siderBar">侧边栏,宽度固定200px</div>
    <div class="content">内容区,宽度自适应</div>
</body>

自适应两列布局

这时候改变浏览器的宽度,可以看出右侧内容区可以自动适应浏览器。

元素垂直居中

用负margin+position:absolute可以实现block元素、inline元素以及inline-block元素的垂直居中。

.father {
    position: relative; // 控制子元素在父元素之内
    width: 500px;
    height: 500px;
    background-color: cornflowerblue;
}
.son {
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -100px; // 元素height一半的负数
    margin-left: -50px; // 元素
    width: 100px;
    height: 200px;
    background-color: white;
}

元素垂直居中

原理是:绝对定位的top: 50%; left:50%;只是定位了son元素左上角的点的位置,而margin-topmargin-left将自己拉回了宽高一半,将自己的中心点变成中心。

tab选项卡

利用负margin技术可以实现选项卡的样式设计。
如下代码:

<style>
  ul, li {
    list-style: none;
  }
  .tab {
    width: 400px;
  }
  .tabHd {
    margin-bottom: -1px;
    padding: 0 10px 0 0;
    border: 1px solid #6c92ad;
    border-bottom: none;
    background: #eaf0fd;
    height: 28px;
  }
  .tabList {
    float: left;
    margin-left: -1px;
    padding: 0 15px;
    line-height: 28px;
    border-left: 1px solid #6c92ad;
    border-right: 1px solid #6c92ad;
    color: #005590;
    text-align: center;
  }
  .tabList.current {
    position: relative;
    background: #fff;
  }
  .tabBd {
    border: 1px solid #6c92ad;
  }
  .tabBd .roundBox {
    padding: 15px;
  }
  .tabContent {
    display: none;
  }
  .tabContent.current {
    display: block;
  }
</style>
<div id="tab" class="tab">
  <ul class="tabHd">
    <li class="tabList current">tab 1</li>
    <li class="tabList">tab 2</li>
    <li class="tabList">tab 3</li>
    <li class="tabList">tab 4</li>
  </ul>
  <div class="tabBd">
    <div class="roundBox">
      <div class="tabContent current">选项内容1</div>
      <div class="tabContent">选项内容2</div>
      <div class="tabContent">选项内容3</div>
      <div class="tabContent">选项内容4</div>
    </div>
  </div>
</div>

效果如下:

负margin实现选项卡

代码中用到了两个负margin,一个用于tabList,通过向右边“拉”用来重叠每个tab项的border
另一个用于tabHd,通过向上“拉”,并且设置当前选项的背景色为白色,将选项内容覆盖住当前选项的下border,而其余tab项由于没有设置背景色默认为透明,于是不会被遮罩住。