CSS经典布局回顾

圣杯布局(经典三列布局)

布局要求:
1、三列布局,中间宽度自适应,两边定宽;
2、中间栏要在浏览器中优先展示渲染;(所以html中中间栏写在左右栏前面)
3、允许任意列的高度最高;
4、要求只用一个额外的DIV标签;
5、要求用最简单的CSS、最少的HACK语句;

实现方法:

1
2
3
4
5
<div class="box">
<div class="main">Main</div>
<div class="left">Left</div>
<div class="right">Right</div>
</div>

1.利用浮动,margin负值,相对定位,一个额外div包住这三栏
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
.box{
padding-left: 200px;
padding-right: 150px;
overflow: hidden; zoom: 1;/* 清浮动 */
min-width: 550px; /* 可用性的考虑,防止窗口缩小时中间栏消失,一般可设为 两边left宽度+right宽度 */
}
.left{
height: 30px;
width: 200px;
float: left;
margin-left: -100%;
background: #ccc;
position: relative;
left: -200px;
_left: 150px;/* IE6 hack 这个值是右边栏的宽度*/
}
.main{
width: 100%;
height: 100px;
background: #9cf;
float: left;
}
.right{
width: 150px;
height: 50px;
float: left;
margin-left: -150px;
background: #fcc;
position: relative;
right: -150px;
}

Main的宽度100%,left和right定宽,我们设为经典的200px,150px,三者都加浮动,float: left;此时由于main宽度为100%,所以left和right上不去,浮在它下面(注意给父级清浮动)

为left栏设置margin-left: -100%;为右边栏设置 margin-left: -150px; 此时左右栏浮上去了,但是盖在main的上面,会遮住Main的内容

为这三栏的父级div设置padding-left: 200px; padding-right: 150px; 留出左右栏的宽度,但是此时由于父级的padding左右栏也缩进来了

为左右栏加相对定位,各自相对于自己把自己挪出去,即可得到圣杯布局

demo演示

2.利用相对父级绝对定位,margin值,一个额外div包住这三栏
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.box{
position: relative;
min-width: 550px;
}
.left{
width: 200px;
height: 30px;
background:#ccc;
position: absolute;
top: 0;
left: 0;
_left: -200px; /* IE6 hack */
}
/* Main宽度为auto */
.main{
width: auto;
height: 100px;
background: #9cf;
margin-left: 200px;
margin-right: 150px;
}
.right{
width: 150px;
height: 50px;
background:#fcc;
position: absolute;
right: 0;
top: 0;
}

Main的宽度为auto,left和right定宽,我们设为经典的200px,150px,此时按html结构顺序排列如下

为left栏和right栏设置相对于父元素的绝对定位 此时左右栏便上去了,但是盖在main的上面,会遮住Main的内容

main设置margin-left: 200px; margin-right: 150px; 留出左右栏的宽度,即可得圣杯布局

demo演示

2.双飞翼布局

圣杯布局的改良,效果一样,但是实现简单一些

利用浮动,margin负值,两个额外的div
1
2
3
4
5
6
7
8
<div class="box">
<div class="main">
<div class="inner">Main</div>
</div>
<div class="left">Left</div>
<div class="right">Right
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.box{
overflow: hidden; zoom: 1;/* 清浮动 */
min-width: 550px; /* 可用性的考虑,防止窗口缩小时中间栏消失 */
}
.left{
background: #ccc;
width: 200px;
height: 30px;
float: left;
margin-left: -100%;
}
.main{
width: 100%;
float: left;
}
.right{
background: #fcc;
width: 150px;
height: 50px;
float: left;
margin-left: -150px;
}
.inner{
background: #9cf;
height: 100px;
margin-left: 200px;
margin-right: 150px;
}

Main的宽度100%,left和right定宽,我们设为经典的200px,150px,三者都加浮动,float: left;此时由于main宽度为100%,所以left和right上不去,浮在它下面(注意给父级清浮动)

为left栏设置margin-left: -100%;为右边栏设置 margin-left: -150px; 此时左右栏浮上去了,但是盖在main的上面,会遮住Main的内容

再在新加的类名为inner的div上设置margin-left: 200px; margin-right: 150px; 给出两边栏的宽度即可得到双飞翼布局

demo演示
与圣杯布局的实现不同在于:

  • 双飞翼布局的HTML结构多了一个div(.inner),这个div是加给main内层的
  • 不需要父级div的padding,不需要左右栏的相对定位,只需要浮动和margin负值

3.等高布局

布局要求:
多列的高度保持一致,任一列的高度变化,其他列也变化

使用正的padding值和负的margin值对冲实现

在所有列中使用正的padding-bottom和负的margin-bottom,在所有列外面加上一个div,并设置这个div的overflow:hiden把溢出背景切掉即可得到等高布局,一般会把padding的margin的值设的很大。原理可以参见负margin原理
这个方法的缺陷是,那就是如果要实现每列四周有边框效果,那么每列的底部(或顶部)将无法有边框效果。

为所有列加浮动float: left,顺便加上5px的border后,情况如下:

现在为所有列加上padding-bottom: 9999px;margin-bottom: -9999px;变成了下面这样,等高布局就出来了

当然,它的缺陷也出来了,底部边框不见了,加了那么大的padding值,父级还overflow了当然看不到了。
解决这个边框问题可以在每一列里面加上一个div,然后对这个div相对于所有列的父级div进行绝对定位,并设置高度和背景颜色模拟边框。这里的高度注意IE下的最小高度bug。这种方法需要依赖每一列的宽度。
还有一种方法是在所有列外面加一层div,并做一张边框背景图来模拟边框
我们采用第一种,进行相关操作后,变成了下面这样

改变任一列的高度,可看到其他列也变化了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<div class="wrap">
<div class="box left">
页面内容<br/>
页面内容<br/>
页面内容<br/>
页面内容<br/>
页面内容<br/>
<div class="bottom1"></div><!-- 模拟下边框 -->
</div>
<div class="box center">
页面内容<br/>
页面内容<br/>
页面内容<br/>
页面内容<br/>
页面内容<br/>
页面内容<br/>
<div class="bottom2"></div>
</div>
<div class="box right">
页面内容<br/>
页面内容<br/>
页面内容<br/>
页面内容<br/>
页面内容<br/>
页面内容<br/>
页面内容<br/>
页面内容<br/>
<div class="bottom3"></div>
</div>
</div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
.wrap{
width:800px;
margin:0 auto;
overflow:hidden;
position: relative;/* 因为模拟边框要相对于这里绝对定位 */
}
.box{
float:left;
padding-bottom:10000px;
margin-bottom:-10000px;
}
.left{
width:200px;
background: #6fa8dc;
border: 5px solid #333;
}
.center{
width:200px;
background:#ffd966;
border: 5px solid #888;
}
.right{
width:300px;
background: #93c47d;
border: 5px solid #ccc;
}
/* 以下是模拟边框部分 */
.bottom1{
position: absolute;
bottom: 0;
left: 0px;
width: 210px;
height: 5px;
background: #333;
overflow: hidden; /*解决IE下最小高度 */
}
.bottom2{
position: absolute;
bottom: 0;
left: 210px;
width: 210px;
height: 5px;
background: #888;
overflow: hidden;
}
.bottom3{
position: absolute;
bottom: 0;
left: 420px;
width: 310px;
height: 5px;
background: #ccc;
overflow: hidden;
}

demo演示

2.使用边框模仿等高列,并不是真的等高列

这种方法比较适合两列或者三列,主要思路是将left列的border-right设成right列的宽度,并设置该边框的颜色与right列的背景色相同,而列的父级div的背景颜色设置为与列left的背景色相同。具体实现还要用到浮动与margin负值。这种方法感觉也有许多局限性,但是兼容性没问题

为所有列加浮动float: left

将left列的border-right设成right列的宽度,并设置margin-right为border-right的负值,此时已经可以实现left列高度变化时right列高度也变化

再将父级div的背景色设为left列的背景色,以便实现right列高度变化时left列也变化,就完成了视觉上的等高布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<div class="wrap">
<div class="left">
页面内容<br>
页面内容<br>
页面内容<br>
页面内容<br>
页面内容<br>
页面内容<br>
页面内容<br>
页面内容<br>
页面内容<br>
</div>
<div class="right">
页面内容<br>
页面内容<br>
页面内容<br>
页面内容<br>
页面内容<br>
页面内容<br>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.wrap{
width: 800px;
margin: 0 auto;
background: #0ff;
overflow: hidden;
}
.left{
width: 300px;
border-right: 500px solid #666;
margin-right: -500px;
background: #0ff;
float: left;
}
.right{
width: 500px;
background: #666;
float: left;
}

demo演示

3.利用背景嵌套与相对定位(固定布局)

这种方法的实现的原则是:任何div元素的最大高度来撑大其他的div容器高度。看下面的原理图

不管哪一列的高度最高,外面那三层背景的高度都会随最高列变化而变化,从而实现视觉上的等高布局
背景层的宽度均为100%,从第二层背景div开始用相对定位往左偏移出自身右边的列的宽度。
背景层相对定位后会溢出,所以最外层容器还要加overflow,而且每一列还要相对定位,偏移量为最近父级的溢出宽度,相对定位完后再浮动到同一行。
这种方法是不需要借助其他东西(javascript,背景图等),而是纯CSS和HTML实现的等高列布局,并且能兼容所有浏览器(包括IE6),并且可以很容易创建任意列数。有多少列就要有多少层背景div。

1
2
3
4
5
6
7
8
9
10
11
<div class="container">
<div class="rightWrap wrap">
<div class="centerWrap wrap">
<div class="leftWrap wrap">
<div class="left">left</div>
<div class="center">center</div>
<div class="right">right</div>
</div>
</div>
</div>
</div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
.container {
width: 960px;
margin: 0 auto;
}
.rightWrap{
width: 100%;
background: green;/* right列的背景色 */
/* center和left列的背景色会在左边溢出,所以加overflow: hidden隐藏; 顺便可以清浮动*/
overflow: hidden;
/* IE6下子元素有相对定位时,overflow是包不住的,所以给父级加定位解决*/
position: relative;
}
.centerWrap{
width: 100%;
background: yellow;/* center列的背景色 */
position: relative;
/* 相对于自身向左偏移出right列的宽度*/
right: 320px;
float: left;/* 清浮动 */
}
.leftWrap{
width: 100%;
background: pink; /* left列的背景色 */
position: relative;
/* 相对于自身向左偏移出center列的宽度,由于父级centerWrap定位偏移了right的宽度,
所以leftWrap也跟着移动了。此时只需偏移center的宽度就可以了 */
right: 420px;
float: left;/* 清浮动 */
}
/* 由于父级leftWrap的宽度是100%也就是960px,相对定位完后,有740px(320px+420px)溢出了,所以每一列需要相对自身右移740px,再对每一列设置浮动以并到同一行 */
.left{
width: 220px;
position: relative;
left: 740px;
float: left;
}
.center{
width: 420px;
position: relative;
left: 740px;
float: left;
}
.right{
width: 320px;
position: relative;
left: 740px;
float: left;
}

demo演示

4.利用背景嵌套与相对定位(适应布局)

将上面那个方法中的宽度改为百分比形式即可

5.使用背景图片,在列的父元素上使用这个背景图进行Y轴的铺放,从而实现一种等高列的假像
6.使用display: table系列模拟表格实现等高列