css中的负边距(negative margin)是布局中的一个常用技巧,只要运用得合理常常会有意想不到的效果。很多特殊的css布局方法都依赖于负边距,所以掌握它的用法对于前端的同学来说,那是必须的。本文非常基础,老鸟可以略过。
一、负边距对元素宽度的影响
负边距不仅能影响元素在文档流中的位置,还能增加元素的宽度!
这个作用能实现的前提是:该元素没有设定width属性(当然width:auto是可以的)。
比如,下图的黑灰色部分是一个块状元素,它没有设定宽度。它被包裹在一个宽度为400px,且水平居中的父元素中。
<!DOCTYPE html>
<html>
<head>
<style>
.container {
width: 400px;
height: 200px;
margin: 0 auto;
background-color: antiquewhite;
}
.item {
width: auto;
height: 100px;
background-color: #666666;
}
</style>
</head>
<body>
<div class="container">
<div class="item">我是一个没有心的杀手</div>
</div>
</body>
</html>
现在给这个元素的设一个margin-right:-100px;
<!DOCTYPE html>
<html>
<head>
<style>
.container {
width: 400px;
height: 200px;
margin: 0 auto;
background-color: antiquewhite;
}
.item {
width: auto;
height: 100px;
margin-right: -100px;
background-color: #666666;
}
</style>
</head>
<body>
<div class="container">
<div class="item">我是一个没有心的杀手</div>
</div>
</body>
</html>
我们看到它的宽度的确变长100px,然后再给它设一个margin-left:-100px
<!DOCTYPE html>
<html>
<head>
<style>
.container {
width: 400px;
height: 200px;
margin: 0 auto;
background-color: antiquewhite;
}
.item {
width: auto;
height: 100px;
margin-left:-100px;
margin-right: -100px;
background-color: #666666;
}
</style>
</head>
<body>
<div class="container">
<div class="item">我是一个没有心的杀手</div>
</div>
</body>
</html>
我们看到它变得更宽了。
负的margin会改变元素的宽度,这的确很让人费解,如果说负边距会改变元素在文档流中的位置还是很好理解的话,那改变宽度这种现象还真的蛮让人不可思议的。
那这货有什么用途呢?我就举一个例子吧。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>浮动两端对齐</title>
<style type="text/css">
ul,
li {
margin: 0;
padding: 0;
}
h2 {
clear: both;
font-size: 1.2em;
}
.justify {
width: 320px;
/* 1行3个li,li之间距离10px = 100px*3 + 10px*2 */
overflow: hidden;
margin: 10px;
border: 1px solid #999999;
}
.justify ul {
width: 330px;
/* 可容纳下3列的宽度 */
margin-bottom: -10px;
/* 隐藏掉最下面一行的margin-bottom */
overflow: hidden;
zoom: 1;
/* 触发IE的Layout */
}
*+html .justify ul {
margin-bottom: 0;
/* 针对IE7中最后1行li的margin-bottom失效 */
}
.justify li {
display: inline;
float: left;
list-style: none;
width: 100px;
height: 100px;
margin: 0 10px 10px 0;
background: #EEEEEE;
}
.margin ul {
width: auto;
margin: 0 -10px -10px 0;
}
.col-2 {
width: 210px;
}
.col-4 {
width: 430px;
}
</style>
</head>
<body>
<div>
<a href="http://www.ddcat.net/blog/?p=1199" title="回到猫窝Blog">回到猫窝Blog</a>
</div>
<h1>浮动两端对齐</h1>
<h2>ul定宽</h2>
<div class="justify">
<ul>
<li>靠左边</li>
<li>中间</li>
<li>靠右边</li>
<li>靠左边</li>
<li>中间</li>
<li>靠右边</li>
<li>靠左边</li>
<li>中间</li>
<li>靠右边</li>
</ul>
</div>
<h2>ul使用负margin值</h2>
<div class="justify margin">
<ul>
<li>靠左边</li>
<li>中间</li>
<li>靠右边</li>
<li>靠左边</li>
<li>中间</li>
<li>靠右边</li>
<li>靠左边</li>
<li>中间</li>
<li>靠右边</li>
</ul>
</div>
<h2>两列</h2>
<div class="justify margin col-2">
<ul>
<li>靠左边</li>
<li>靠右边</li>
<li>靠左边</li>
<li>靠右边</li>
<li>靠左边</li>
<li>靠右边</li>
</ul>
</div>
<h2>四列</h2>
<div class="justify margin col-4">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
</ul>
</div>
<div>
<a href="http://www.ddcat.net/blog/?p=1199" title="回到猫窝Blog">回到猫窝Blog</a>
</div>
</body>
</html>
div元素:<div class="justify margin">
div>ul元素:
.margin ul {
width: auto;
margin: 0 -10px -10px 0;
}
一个负的margin-right,相当于把ul的宽度增加了10px。
二、负边距对浮动元素的影响
负边距对浮动元素的影响与负边距对文档流中元素的影响其实是差不多的。文档流中元素的位置由文档流的走向决定,浮动的元素也可以看成有一个“浮动流”存在,不过浮动流既可以向左,也可以向右。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.item {
float: left;
width: 100px;
height: 100px;
/* margin-right:-50px; */
}
.d1 {
background-color: #0099fe;
}
.d2 {
background-color: #996633;
}
.d3 {
/* margin-left:-80px; */
background-color: #ff6633;
}
</style>
</head>
<body>
<div class="item d1">元素1</div>
<div class="item d2">元素2</div>
<div class="item d3">元素3</div>
</body>
</html>
以上代码是三个向左浮动的元素,宽高都是100px:如下图
现在把它们都设一个 margin-right:-50px; 然后会变成这样子:我们看到后面的元素叠到了前面的元素上。
我们注释掉 margin-right:-50px; 接着,我们把浏览器逐渐缩小,然后因为宽度不够,元素3掉下来了。
我们给元素3设一个margin-left:-80px;看看会怎么样:如下图所以,这时我们看到元素3上去了,而且还覆盖了元素2的一部分。
继续把元素3的 margin-left:-80px 设为 margin-left:-100px,这时元素3完全覆盖住了元素2。
当把元素3设为:margin-left:-200px时:我们看到元素3继续向左移动并覆盖住了元素1。
我们继续,当把元素3设为:margin-left:-250px时:我们看到元素3继续向左移动50px,也就是说目前已经跑出了浏览器外50px。是的,你没看错,它跑出了浏览器之外!
现在想必大家都明白了负边距对浮动元素位置的影响了吧。所以那些说得很好听的什么圣杯布局、双飞翼布局什么的,都是利用这个原理实现的。就是某个元素虽然是在网页布局结构上把代码写在了后面,但可以通过负边距让它在浏览器显示的时候展示在其他元素前面。——关于实例可参看文章:CSS | CSS实现两栏布局和三栏布局方法详解中关于实现三栏布局中负margin的使用。
三、负边距对绝对定位元素的影响
绝对定位的元素定义的top、right、bottom、left等值是元素自身的边界到最近的已定位的祖先元素的距离,这个元素自身的边界指的就是margin定义的边界,所以,如果margin为正的时候,那它的边界是向外扩的,如果margin为负的时候,则它的边界是向里收的。利用这点,就有了经典的利用绝对定位来居中的方法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
padding: 0;
margin: 0;
}
div {
width: 100px;
height: 100px;
background-color: #f00;
position: absolute;
left: 50%;
top: 50%;
/* 向左移动div元素宽度的一半 */
margin-left: -50px;
/* 向上移动div元素高度的一半 */
margin-top: -50px;
}
</style>
</head>
<body>
<div>我是一个div</div>
</body>
</html>
看下效果:
但该方法的缺点是必须要知道要居中元素的高度和宽度。
参考资料:
CSS双飞翼布局和圣杯布局margin-left:-100% - CSDN博客
CSS圣杯布局中margin-left:-100%的含义 - 简书
理解margin-left:-100% - 紫色,风铃 - 博客园
圣杯布局中对left盒子设置margin:-100%的一点解释