首先以下面这个例子做分析
要实现的效果为三栏布局,它的特点:两边定宽,然后中间的width是auto的,可以自适应内容,再加上margin边距,来进行设定。(如果是3个宽度固定大小无需中间自适应的div则直接都用float即可,同时html结构是left,main,right的顺序)如下所示
代码如下
<!DOCTYPE html>
<html>
<head>
<style>
.wrapper{
overflow: hidden; //清除浮动
}
.middle{
width: 100%;
float: left;
}
.middle .main{
margin: 0 200px;
height:300px;
background: red;
}
.left{
width: 200px;
height: 300px;
float: left;
background: green;
margin-left: -100%;
}
.right{
width: 200px;
height: 300px;
float: left;
background: yellow;
margin-left:-200px
}
</style>
</head>
<body>
<div class="wrapper">
<div class="middle">
<div class="main">中间</div>
</div>
<div class="left">
左栏
</div>
<div class="right">
右栏
</div>
</div>
</body>
</html>
为了使中间main宽度自适应而两边left和right宽度固定,需要先固定main的margin,这样当窗口宽度缩小的时候会缩小main的content宽度而margin保持不变(margin保留的固定宽度200px刚好用来放left和right盒子)。
为什么main需要一个middle的父盒子呢?或者说为什么不直接用middle盒子而非要加个子盒子main呢?
这是因为float盒子可以在float盒子上方悬浮(middle,left,right都为float盒子)而无法在普通盒子上悬浮(普通盒子在文档流中而float盒子脱离了文档流,1个float盒子和1个普通盒子并列时float盒子在普通盒子的正上方或正下方,相当于1个或一堆连续的float盒子和1个或一堆连续的普通盒子互相遇到时在对方正下方新开辟一个区域,不能互相叠加或覆盖或悬浮对方上面,margin也不会合并,但可以互为父子关系,此时需慎用,小心如普通盒子包含float盒子造成的float泄露等问题---BCF解决),而当middle的float: left去掉时,middle变为了普通盒子,此时可以测试一下left不同margin-left值(负值)下的情形(为了简便将right的div注释掉或删掉)
当left的margin-left=0px,-100px,-180px,-200px且middle非float盒子时的情形
0px
-100px
-180px
-200px
可以看到,当left的margin-left负值的绝对值越大时,left越向左移,而当值为-200px也就是向左移动200px(left的宽度)时,由于此时middle不是float盒子而是普通盒子,right的margin无法悬浮在前一个(即非float盒子middle)的上方,故直接消失了。
而当middle设置为float盒子时,left的margin-left(负数绝对值>=200px)为-200px时就可以悬浮在middle上,情形如下:
表明当某行的float盒子的margin-left负值大小使得其完全(或刚好完全消失)时,若上一行的盒子为float盒子(这里比较特殊,middle的width=100%,故应该是上一行的最后一个盒子且同时是float盒子),则本行本应消失的盒子移到上一行
由于main的左右margin为200px,刚好为left及right的宽度,故可以看到这里实现的是右栏的固定即中间栏的自适应(图中显示的是左栏是因为作为例子的关系),而如何使左栏放在其正确的位置上呢?用margin-left的值为某个px并不合适,因为窗口宽度会变,那用什么呢?答案是用left的margin-left:-100%;这个百分比是窗口宽度的百分比,由于html结构中left是middle的下一个盒子,且middle是占据整行的(其width=100%),也即left是middle下一行的最左边,故通过margin-left:-100%平移一个窗口长度即可使得left放置在正确位置,如下:
此时再将right放在正确位置上,由于在html结构中盒子的前后次序是middle,left,right,当left和middle的位置确定后,若不处理right的margin,则right会在middle下一行的最左边(left已移动到上一行),如下:
则将right的margin-left设置为自身宽度的负值即可,即-200px,此时right也放置在了正确位置上