了解margin负值之美:
在我们去写这些布局之前,需要了解一个特性,即margin为负值时产生的效果:
.test {
width: 200px;
height: 200px;
display: inline-block;
background-color: #0f0;
}
<div class='test'>我是盒子的内容</div>
这只是个正常的标准盒子,但我们在样式里追加:
margin-left: -200px
发生了什么呢?这个盒子会移动到浏览器最左边去,即是200px,由于浏览器浏览器默认margin为8px,所以我们只能看到盒子的8px的宽度;margin-right: -200px;
又发生了什么呢?这个盒子没发生任何的改变,按理说margin-left:-200px
时盒子向左移动200px,当margin-right: -200px;
也应向右移动200px啊,为什么它的位置没有发生任何改变呢?其实这是一个障眼法,即你眼所看并非真实:
这里我们要知道一个盒子的真实宽度为:内容宽度 + 左边和右边的padding值 + 左边和右边的border值 + 左边和右边的magin值
所以这时盒子的真实宽度为200px + (-200px) = 0,只不过内容宽度不变,我们肉眼看到的它并没有发生改变,其实它现在的宽度已变成0了,我们在其后加上一个行内元素:<span>我是后来的,检测盒子的宽度</span>
,结果如下:
看到了什么???这里后来添加的span标签内容完全覆盖了原先盒子的内容,更加说明了此时的盒子已没有宽度了,我们看到的不过是内容的宽度罢了,我们记住下面的结论:
1: 给元素设置margin只会影响相邻元素摆放位置、自己的摆放位置、自己的总宽度、自己的总高度,并不会影响自己的内容宽度或高度的显示。
2: 给元素margin-left、margin-right设置负值,不会影响内容宽度显示,但元素总宽度会改变,每个元素的摆放位置是根据总宽度、总高度来进行摆放的
,虽然元素的内容宽高会完全显示,但设置负值的那部分距离对其它元素位置摆放没有影响,这部分距离是显示在相邻元素的上边还是下边,是要根据每个元素的层级来决定的。
这里我们就发现了即使不用浮动、定位,标准盒子自己也能发生相应的’层级效果‘(这里只是看效果是这样的),我们可以继续给盒子添加样式:
position: relative;
z-index: 1;
这个盒子自然就会浮现在span标签的上面了。
好了,有了这些认识,我们继续探讨。
浮动与margin为负值结合使用
1.首先我们是左浮动
与margin-left为负值
的深究:
body {
font-size: 30px;
font-weight: bold;
}
.content {
width: 200px;
height: 300px;
background-color: green;
margin: 100px auto;
}
.center {
float: left;
width: 150px;
height: 150px;
background-color: pink;
}
.left {
float: left;
width: 100px;
height: 100px;
background-color: yellow;
}
<div class="content">
<div class="center">center</div>
<div class="left">left</div>
</div>
初始样式,不难理解,我们虽然给center和left这两个盒子都设置了左浮动,但是由于父盒子的宽度不足于容纳这两个盒子,后来的left盒子就会掉下来,现在我们改变样式:
-
在left盒子里加上语句
margin-left: -50px
发生了什么???
我们从结果看出,left这个盒子成功上位,与它的兄弟center拥抱在一起了,为什么???这也就是前面说的盒子的真实宽度,这里left的真实宽度其实为100px + (-50px) = 50px
了,我们从最初的代码里可以理解,center盒子后面是空了50px的距离,由于浮动关系,left这个盒子必须要与它的亲兄弟center拥抱了。这里我们还会发现left盒子会覆盖center盒子一部分,这里又是涉及到了层级关系了;
结论:后来者居上,后面浮动元素会盖住前面的浮动元素。 -
当
margin-left: -150px
发生了什么???
left元素左边和content容器左边对齐了,此时left盒子的真实宽度为
100px + (-150px) = -50px
,当我们的浮动方向与元素偏移方向相同时,会成功偏移,我们可以粗略认为此时left盒子是透明的了,会继续偏移,故是以上的效果。 -
再重新设置
margin-left: -100%
发生了什么???
当left盒子的margin偏移100%时,即是父盒子content的宽度200px,这时盒子的真实宽度为:100px + (-200px) = -100px
;据上分析,这里出现这样的效果就不难理解了。
2.左浮动与margin-right为负值
的探究:
还原以上代码:
- 当
margin-right: -50px
发生了什么???
当我们设置了这个值后lfet盒子的真实宽度为:100px + (-50px) = 50px
这里也正好符合margin-left: -50px
的情况,会由于浮动原因和center拥抱了,但不同的是,left盒子并没有覆盖住center盒子,我想大概是由于我们设置的是左浮动,而margin-right为负值时盒子本身就应该向右移动,可以看作是拔河,两边的力道均匀,保持了平衡(这里只是我粗略的看法,麻烦大神知道其原因的评论一下);也可以这么说吧:当元素的浮动方向与元素偏移的方向相反时,元素不会成功偏移,在content盒子外多出的left盒子部分相当于没有宽度,即是可以看作是透明的,不会影响内容盒子的展示,所以它并不会向左覆盖center。 - 当
margin-right: -150px
时,发生了什么???
没有发生任何的改变,这也大概的验证了上述的情况,本身盒子应该向右移动,但是由于浮动因素,它位置并没有发生改变。
右浮动与左浮动的本质大同小异。
这里我们可以得出总结:
- 当上一个元素的浮动方向和当前元素margin的方向相反时,该元素不能覆盖上一个浮动元素,最近只能紧贴上一个元素右边
- 当上一个元素的浮动方向和当前元素margin的方向相同时,该元素可以覆盖或远离上一个浮动元素
好了,有了这些认识,我们去探究css的三大重要布局吧!!!
双飞翼布局
左列和右列宽度恒定,中间列的宽度根据浏览器窗口的大小自适应。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>双飞翼布局</title>
<style>
.container {
width: 100%;
}
.column {
float: left;
height: 200px;
}
.left {
width: 300px;
background-color: #0f0;
margin-left: -100%;
}
.center {
width: 100%;
background-color: #f00;
}
.center .content {
margin: 0 300px;
}
.right {
width: 300px;
background-color: #00f;
margin-left: -300px;
}
</style>
</head>
<body>
<div class="container">
<div class="column center ">
<div class="content">center</div>
</div>
<div class="column right ">right</div>
<div class="column left " >left</div>
</div>
</body>
</html>
我们分析一下这个代码:
- 首先我们把center、right、left三个盒子都设上了左浮动,这里注意:必须将center盒子设在另外两个盒子的上边,不然由于后面浮动元素会盖住前面的浮动元素致使left和right盒子被覆盖,不满足需求,left盒子和right盒子倒是无关顺序。
- 左盒子left设置了
margin-left: -100%;
会偏移父盒子的宽度即body的宽度,left盒子自身高度早就为负值了,但是不会影响我们的内容的,所以由于后者居上原理,覆盖了center盒子。 - 右盒子right设置了
margin-left: -300px;
这里盒子的真实宽度为0,同理,但这里提一下,我们若是用了margin-right: -300px;
它就不会得到我们想要的效果了,这是由于用到了上面的结论:当上一个元素的浮动方向和当前元素margin的方向相反时,该元素不能覆盖上一个浮动元素,最近只能紧贴上一个元素右边 - 我们这里在center盒子里再放了一个content盒子就是为了防止left盒子覆盖住center的内容,所以我们可以把内容放在content盒子里并设置了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>
* {
margin: 0;
padding: 0;
}
body {
min-width: 600px;
}
header,
footer {
width: 100%;
height: 100px;
line-height: 100px;
background-color: #2fff99;
text-align: center;
font-size: 30px;
}
.container {
padding: 0 200px;
overflow: hidden; //清除浮动
}
.column {
float: left;
height: 500px;
position: relative;
}
.center {
width: 100%;
background-color: #f00;
}
.left {
width: 200px;
background-color: #0f0;
margin-left: -100%;
left: -200px;
}
.right {
width: 200px;
background-color: #f0f;
margin-left: -200px;
right: -200px;
}
</style>
</head>
<body>
<header>header</header>
<div class="container">
<div class="column center">center</div>
<div class="column left">left</div>
<div class="column right">right</div>
</div>
<footer>footer</footer>
</body>
</html>
其实这里的布局和双飞翼大同小异,不同的是我们给container这个容器设置了padding值,使内容呈中间显示,由于我们在父容器上设置了padding,无论margin-left值为多少,它都不会超过父容器,所以我们需要在父容器上应当设置相对定位,使其不会脱离文档流,用left调整位置。
我们可以改进一下,在center盒子自身上设置padding值,但要变为ie盒子,这样就不需要设置定位了,代码如下:
padding: 0 200px;
box-sizing: border-box;
效果图:
二栏布局
1.两列左侧固定右侧自适应布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>左侧固定右侧自适应布局</title>
<style>
.left,
.right {
color: #fff;
font-size: 25px;
}
.left {
float: left;
width: 150px;
height: 150px;/* 实际开发中,不要给出高度,高度是由内容自行撑开 */
background-color: #f00;
margin-right: -150px;
position: relative; /* 让盒子保留原先的位置 */
}
.right {
float: left;
width: 100%;
height: 150px;
background-color: #0f0;
margin-left: 155px;
}
</style>
</head>
<body>
<div class="left">左侧固定</div>
<div class="right">右侧自适应</div>
</body>
</html>
效果图:
实际用到的原理跟上述差不多的,只不过这里需要注意的是相对定位reletive的作用是让盒子保留原先的位置 ,即它不会被后来的浮动元素所覆盖,至于具体的原因还需深究。。。
2.两列左侧自适应右侧固定布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>左侧自适应右侧固定布局</title>
<style>
.left,
.right {
height: 150px;
color: #fff;
font-size: 25px;
float: left;
}
.left {
width: 100%;
background-color: #f00;
}
.right {
width: 150px;
background-color: #0f0;
margin-left: -150px;
}
</style>
</head>
<body>
<div class="left">左侧自适应</div>
<div class="right">右侧固定</div>
</body>
</html>
效果图:
这里还有一个就是左侧固定右侧也固定的二栏布局,这里就不再举例子了,大同小异。
三栏布局
1.左右定宽,中间自适应布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>三栏布局之中间自适应</title>
<style>
.container {
width: 100%;
/* 清除浮动 */
overflow: hidden;
color: #fff;
font-size: 25px;
}
.left,
.right {
width: 150px;
height: 150px;
float: left;
}
.left {
background-color: #f00;
margin-right: -150px;
position: relative;
}
.center {
float: left;
width: 100%;
height: 150px;
background-color: #0f0;
}
.center .content {
margin: 0 150px;
}
.right {
background-color: #ff0;
margin-left: -150px;
}
</style>
</head>
<body>
<div class="container">
<div class="left">左侧定宽</div>
<div class="center">
<div class="content">中间内容自适应</div>
</div>
<div class="right">右侧定宽</div>
</div>
</body>
</html>
其实这和前面的双飞翼布局就很类似了,只不过我们这里的center盒子并没有放在其余两个盒子的前面,利用了相对定位的特性也能使之达到效果。
效果图:
2.左侧自适应布局 ,中间和右边定宽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>三栏布局之左侧自适应</title>
<style>
.container {
width: 100%;
/* 清除浮动 */
overflow: hidden;
color: #fff;
font-size: 20px;
}
.center,
.right {
width: 150px;
height: 150px;
float: right;
}
.left {
float: left;
width: 100%;
height: 150px;
background-color: #f00;
margin-right: -300px;
}
/* 防止左侧内容被后来的浮动元素覆盖 */
.left .content {
margin-right: 300px;
}
.center {
background-color: #0f0;
}
.right {
background-color: #ff0;
}
</style>
</head>
<body>
<div class="container">
<div class="left">
<div class="content">左侧内容自适应</div>
</div>
<div class="center">中间定宽 </div>
<div class="right">右侧定宽</div>
</div>
</body>
</html>
这里不多分析了,相信看了前面的解释,看到这里,会倍感轻松了吧!
效果图:
3.右侧内容自适应,左中两部分定宽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>三栏布局之右边自适应</title>
<style>
.container {
width: 100%;
/* 清除浮动 */
overflow: hidden;
color: #fff;
font-size: 25px;
}
.left,
.center {
width: 150px;
height: 150px;
float: left;
}
.left {
background-color: #f00;
}
.right {
float: right;
width: 100%;
height: 150px;
margin-right: -300px;
background-color: #0f0;
}
.center {
background-color: #ff0;
}
</style>
</head>
<body>
<div class="container">
<div class="left">左侧定宽</div>
<div class="center">中间定宽</div>
<div class="right">
<div class="content">右侧内容自适应</div>
</div>
</div>
</body>
</html>
这里我们把right盒子设了margin-right: -300px;
,是在原本在body的宽度下减少了300px,因为我们左盒子left和中间盒子center盒子的真实宽度并没有减少,之和为300px,所以我们让right盒子减少了300px,自然就得由于浮动必须上去了,只不过我们这里有了一个小技巧,没有用margin-left: -300px;
left和center盒子使用的是左浮动,此时我们right盒子使用的是margin-right: -300px;
,与其相反,我们要看前面提到过的结论:当上一个元素的浮动方向和当前元素margin的方向相反时,该元素不能覆盖上一个浮动元素,最近只能紧贴上一个元素右边,当然你要是用margin-left: -300px;
也能实现,不过稍微麻烦一点而已。
效果图:
好了,目前为止我们css中这些重要布局就到此结束了,我们再次做一次总结:
- 当上一个元素的浮动方向和当前元素margin的方向相反时,该元素不能覆盖上一个浮动元素,最近只能紧贴上一个元素右边
- 当上一个元素的浮动方向和当前元素margin的方向相同时,该元素可以覆盖或远离上一个浮动元素
- 后来居上:后来的浮动元素可以覆盖住前面的浮动元素,有一种层级关系
- 当我们的margin为负时会减少盒子的真实宽度,当为0或者是小于0时,我们可以说它是透明的了,但它的内容宽度没有改变,所以我们能看到盒子的内容,所见并非所实!!!!
文章到此结束,完结撒花!!!看到这些布局还是很头痛的,需要细细咀嚼,文章内容要是有错误之处,还望指出。
参考文章:
深入理解浮动元素与margin负值用法及三栏布局