前端布局知识点(3)——圣杯布局与双飞翼布局

这是完成百度前端学院2015的task1后对前端布局知识点总结的第三篇博文。上两篇总结了一下overflow属性(前端布局知识点(1)——overflow属性)和负边距及文档流(前端布局知识点(2)——负边距)。

在淘宝UED探讨中诞生的双飞翼布局主要解决了两个需求:

  1. 要求三列布局,左右两边定宽,中间宽度自适应;
  2. 要求浏览器优先渲染中间栏。

其实这两个要求已经有圣杯布局实现了。双飞翼布局是沿着圣杯布局的思路加以改良探讨出来的。两者有什么区别呢?

17.04.27更新:时至今日,Grid 布局为实现各类布局提供了非常简便的解决方案。可以通过CSS Grid布局这样玩这篇文章来对 CSS Grid 进行初步了解。

圣杯布局

我们首先来看看出现时间更早的圣杯布局(这个名字让我想到Fate系列)。圣杯布局用到了浮动、负边距和相对定位来实现需求。

html代码(浏览器按照html中写的顺序渲染,因此div.main写在最前面):

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="yellow header">
task4:header
</div>
<div class="page">
<div id="container">
<div class="main red">main</div>
<div class="left green">left</div>
<div class="right blue">right</div>
</div>
</div>
<div class="yellow footer">
footer
</div>

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
body{
margin: 0;
}
.red{
background-color: red;
}
.blue{
background-color: blue;
}
.green{
background-color: green;
}
.yellow{
background-color: yellow;
}
.page{
padding:0 150px 0 180px;
overflow: hidden;
zoom: 1;
}
.header,.footer{
width: 100%;
height: 100px;
clear: both;
}
.left{
width: 180px;
float: left;
margin-left: -100%;
height: 400px;
position: relative;
left: -180px;
}
.main{
width: 100%;
float: left;
height: 400px;
}
.right{
width: 150px;
float: left;
margin-left: -150px;
height: 400px;
position: relative;
right: -150px;
}

效果图如下:

首先,我们给div.page设置一个左右的padding值,这个值要和左右两边宽度相等。固定好div.page后,再分别设置div.left和div.right。以div.left为例,设置float: left使其浮动,margin-left: -100%,这里将div.left左移至左边与main平齐。再加上 position: relative,left: -180px 固定位置,让它能够挤进左右两边空白的同时不会遮住中间部分。

双飞翼布局

圣杯布局有什么缺陷呢?

  1. 圣杯布局使用了相对定位。这样的话,以后再添加额外标签时布局是有局限性的;
  2. 左右两边的宽度只能为固定像素而不能设定为百分比。因为元素宽度设定为百分比时根据父级元素宽度计算,而我们给父级元素设定了padding值,其宽度不明确。我们无法精确计算所需要的百分比。
  3. 浏览器宽度缩小时,随着两边定宽的部分向中间靠拢,中间部分有被挤下去的可能。

怎么能够优化圣杯布局?淘宝UED探讨的结果是增加一个div。这样,我们就可以不再使用相对布局,而仅仅用浮动和负边距来达到我们的需求。这就是双飞翼布局。

html代码(main内层增加一个div):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div class="page">
<div class="header yellow">
task4:header
</div>
<div id="container">
<div class="main red">
<div class="inner"> //增加的div
main
</div>
</div>
<div class="left green">left</div>
<div class="right blue">right</div>
</div>
<div class="footer yellow">
footer
</div>
</div>

CSS代码(去掉左右栏的相对定位和包裹层的padding,增加新div的margin):

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
.red{
background-color: red;
}
.blue{
background-color: blue;
}
.green{
background-color: green;
}
.yellow{
background-color: yellow;
}
.header,.footer{
width: 100%;
height: 30px;
clear: both;
}
.left{
width: 150px;
float: left;
margin-left: -100%;
height: 400px;
}
.main{
width: 100%;
float: left;
height: 400px;
}
.right{
width: 180px;
float: left;
margin-left: -180px;
height: 400px;
}
.inner{
margin-left: 150px;
margin-right: 180px;
}

效果图如下:

将浏览器宽度缩小,可以看到左右两边宽度一定,中间宽度为自适应。

div.inner的 margin-left: 150px;margin-right: 180px 负责将两边内容挤开,避免在没有padding的包裹层时两边内容遮住中间。

参考资料

CSS圣杯布局

css双飞翼布局

上面两篇出自同一作者,可谓一语道破,清晰明了。

圣杯布局的实现过程

双飞翼布局介绍-始于淘宝UED

CSS双飞翼布局_百度知道