圣杯布局与双飞翼布局的相同点与不同点

三栏式布局是众多网页的常规布局之一,我们在采用三栏式布局时所提出的要求一般是左栏与右栏定宽,中间部分宽度自适应,中间部分作为内容主体,我们需要将其放在左栏与右栏之前来达到优先渲染的效果。

2006年Matthew Levine在《A LIST APART》上发表了一篇名为《In Search of the Holy Grail》的文章,提出了圣杯布局的思路。利用负外边距来实现我们需要的效果,充分体现了CSS的艺术与负外边距的强大。

之后淘宝提出了为了实现同样的效果提出了双飞翼布局的思路,同样使用了负外边距来移动栏目从而达到目的。因此,圣杯布局和双飞翼布局有着相似的思路,但是在某些细节上也有不同点。


相同点

首先,我们建立好左中右三栏,因为中间栏需要优先渲染,我们将其放在最前面。

1
2
3
4
5
<div id="content">
<div id="main">main</div>
<div id="left">left</div>
<div id="right">right</div>
</div>

要实现左中右的水平排列,我们要将块状元素浮动。

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

假设左栏定宽200px,右栏定宽120px。(为了看清楚效果,我们暂时为三栏设置一个背景色,同时设置不同的高度以便观察div之间是否重叠)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#main, #left, #right {
float: left;
}
#left {
background-color: red;
height: 100px;
width: 200px;
margin-left: -100%;
}
#main {
background-color: green;
height: 150px;
width: 100%;
}
#right {
background-color: blue;
height: 100px;
width: 120px;
}

得到如下效果:

接下来就要使用到强大的负外边距了,我们先处理左栏,因为中间栏的宽度为100%,所以左栏被挤到下面去了。现在left要到最左边的位置,所以我们在left的样式下输入:

1
margin-left: -100%;

可以看到left已经顺利的被拉回来了。

right同理,它靠在最右边。所以输入:

1
margin-left-120px

得到效果:


以上的步骤,圣杯布局和双飞翼布局是一模一样的。


不同点


圣杯布局

经过以上的设置,出现了一个问题,就是left、right都和main重叠了,我们需要把main缩回来,现在它的宽度充满了整个父元素content,并且随着父元素的变化而变化,我们对父元素进行设置。

1
2
3
#content {
padding: 0 120px 0 200px;
}

但是left和right都在content里,也受到影响被拉进来了。

所以我们要分别让left往左移,right往右移到它们该在的位置上去,为了让它们移动,我们需要在left和right的样式下设置:

1
position: relative;

并且对left设置:

1
left: -200px;

对right设置:

1
right-120px

这样我们就能的到我们所想要的三栏式布局的效果了。

圣杯布局CSS代码:

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>三栏式布局</title>
<style type="text/css">
* {
margin:0;
padding:0;
}
#main, #left, #right {
float: left;
}
#left {
background-color: red;
height: 100px;
width: 200px;
margin-left: -100%;
position: relative;
left: -200px;
}
#main {
background-color: green;
height: 150px;
width: 100%;
}
#right {
background-color: blue;
height: 100px;
width: 120px;
margin-left: -120px;
position: relative;
right: -120px;
}
#content {
padding: 0 120px 0 200px;
}
</style>
</head>
<body>
<div id="content">
<div id="main">main</div>
<div id="left">left</div>
<div id="right">right</div>
</div>
</body>
</html>


双飞翼布局

面临同样的问题,圣杯布局是对三栏的父元素的内边距进行了设置,而双飞翼布局则是从另一个角度入手。既然左右两边要被left和right独享,那main就不要这两边了,那就不会重叠了。

我们创造一个新的div在main的里面,并且把内容都放在这个main的子元素里。

1
<div id="main"><div id="main_in">main</div></div>

并且给它设置左右的外边距,让出左右栏目的位置就可以实现我们需要的效果了。

1
2
3
4
5
6
#main_in {
background-color: grey;
height: 150px;
margin-left: 200px;
margin-right: 120px;
}

效果如下:

(去掉main的背景色即可,效果图没有去掉是为了方便展示main_in的效果!)

双飞翼布局代码:

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>三栏式布局</title>
<style type="text/css">
* {
margin:0;
padding:0;
}
#main, #left, #right {
float: left;
}
#left {
background-color: red;
height: 100px;
width: 200px;
margin-left: -100%;
}
#main {
background-color: green;
height: 150px;
width: 100%;
}
#right {
background-color: blue;
height: 100px;
width: 120px;
margin-left: -120px;
}
#main_in {
background-color: grey;
height: 150px;
margin-left: 200px;
margin-right: 120px;
}
</style>
</head>
<body>
<div id="content">
<div id="main"><div id="main_in">main</div></div>
<div id="left">left</div>
<div id="right">right</div>
</div>
</body>
</html>


效果在线预览:http://zhaoyuxiang.cn/task1-3/