关于你不可不知的“圣杯布局”

本文用两种方式来实现“圣杯布局”

圣杯布局格式要求:

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

就是这个圣杯


传统方式实现的圣杯布局

1
2
3
4
5
6
7
8
//HTML代码
<div class="header">header</div>
<div class="container">
<div class="main">main</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
<div class="footer">footer</div>

将主体main部分写在最前面可以使页面的核心部分优先渲染,这样做的好处就是用户可以首先看到页面的最核心部分的内容,考虑到了用户体验。

1. 设置基本样式:

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
//CSS基本样式设置
*{
margin: 0;
padding: 0;
}
body
{
min-width: 700px;
}
.header,.footer{
border: 1px solid #333;
background-color:white;
text-align: center;
}
.left,.main,.right{
min-height: 130px;
}
.container{
border:2px solid blue;
}
.left{
width:200px;
background:yellow;
}
.right{
width:220px;
background:pink;
}
.main{
background:blue;
}

设置完成之后效果是这样的:

基本样式下的效果

2. 主体的三个子元素设置向左浮动:

1
2
3
.left,.right,.main {
float:left;
}

此时是这样的:

浮动后的样式
我们看一下上面的效果比较明显的两个问题,一是footer跑到上面去了,二是container容器高度塌陷了,这是典型的“清除浮动和闭合浮动”问题。

3. 解决浮动问题:

给footer添加清除浮动,使其左右不允许出现浮动元素。
给container添加

1
2
3
4
5
```
.container {
border:2px solid blue;
overflow:hidden;
}

1
2
3
.footer {
clear:both;
}

此时的效果:

4. 设置main宽度为100%:

1
2
3
4
.main {
width:100%;
background:blue;
}

5. 使left模块和right模块占据合适的位置:

1
2
3
4
5
6
7
8
9
10
.left{
margin-left: -100%;
width: 200px;
background: red;
}
.right{
margin-left: -220px;
width: 220px;
background: green;
}

负的margin-left会让元素沿文档流向左移动,如果负的数值比较大就会一直移动到上一行。

6. 关于覆盖问题:

首先给container的左右加上一个内边距,分别为left和right的宽度。

把left和right分别移动到这两个留白就可以了。可以使用相对定位移动left和right部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.left,.main,.right{
position: relative;
float: left;
min-height: 130px;
}
.left{
margin-left: -100%;
left: -200px;
width: 200px;
background: red;
}
.right{
margin-left: -220px;
right: -220px;
width: 220px;
background: green;
}

至此,我们就实现了圣杯布局:
圣杯布局

传统方式实现的圣杯布局代码很多,步骤稍显复杂,而且我们了解了flex布局之后考虑到使用flex实现圣杯布局。


Flex布局实现圣杯布局

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
*{
box-sizing:content-box;/* 伸缩项目自动box-sizing:border-box,所以需调整为content-box */
margin:0;
padding:0;
}
body{
display:flex;
flex-direction:column;/* 头、中部、脚纵向显示 */
}
header,footer{
flex:0 0 20px;/* 头、脚尺寸固定,不放大、不缩小 */
background:white;
border:1px solid black;
}
.main{
display:flex;
border:1px solid black;
/*
flex:1 == 1 1 auto:剩余空间放大比例(flex-grow) 空间不足缩小比例(flex-shrink) 分配多余空间之前项目占据的主轴空间(flex-basis)
flex:1指的是:中部区域自由伸缩
auto指的是项目本来大小,因未给main设置高度,main高度由子元素最高者决定,若子元素高度为0,则main高度为0
块级元素未主动设置高度或未被子元素撑起高度,浏览器默认为块级元素分配高度为0。
*/
flex:1;
}
.content{
background:blue;
height:80px;
/*
横向中间内容区自适应,即使未指定宽度,但会分配宽度
块级元素未主动设置宽度或未被子元素撑起宽度,浏览器默认为块级元素分配宽度为可使用的全部宽度,比如全屏宽。
*/
flex:1;
}
.left,.right{
height:80px;
background:yellow;
flex:0 0 100px;/* 左右两列固定宽 */
}
.left{
order:-1;/* 让left居于左侧 */
}

效果:

Flex实现圣杯布局

在实现圣杯布局过程中产生了浮动元素设置clear:both失效的疑问,所以在segmentFault上提问如下,也有人解答了:
关于浮动元素设置clear:both失效问题