圣杯布局与双飞翼布局小结

在学习CSS布局中,三栏布局中的圣杯布局和双飞翼布局应用很广泛,并不是说完成左右宽度固定中间宽度自适应这类布局的时候一定要用这两个布局的原理去实现,实现同一个布局的方法很多,我们应该根据需求去选择。

不论是圣杯布局还是双飞翼布局其HTML的DOM结构都是按照中间—左侧—右侧的顺序,相应地也是按这个顺序进行加载,也就是我们常说的“重要的内容先加载”。

圣杯布局

STEP 1: CREATE THE FRAME

先写好整体框架

1
2
3
<div id="header"></div>
<div id="container"></div>
<div id="footer"></div>

用希望左右列占据的宽度作为内边距填充容器

1
2
3
4
#container {
padding-left: 200px; /* 左列宽度 */
padding-right: 150px; /* 右列宽度 */
}

STEP 2: ADD THE COLUMNS

加入具体的左中右三列,注意中间要放在前面

1
2
3
4
5
6
7
<div id="header"></div>
<div id="container">
<div id="center" class="column"></div>
<div id="left" class="column"></div>
<div id="right" class="column"></div>
</div>
<div id="footer"></div>

接着相应的CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#container .column {
float: left;
}
#center {
width: 100%; /*指的是除了padding的container的div宽度*/
}
#left {
width: 200px;
}
#right {
width: 150px;
}
#footer {
clear: both;
}

由于中间列宽度是100%,所以左列和右列被挤到下面了

STEP 3: PULL THE LEFT COLUMN INTO PLACE

现在需要将左右两列给弄到上面中间列左右空出来的padding的位置去

中间列已经在它该在的位置了,所以先不处理它

1
2
3
4
#left {
width: 200px;
margin-left: -100%;
}

这里用100%的负边距将左列移到中间列的最左侧,这100%表示的是container这个div的宽度,也相当于中间列的宽度。现在左列已经上去了,但没有去到该去的位置(padding-left:200px),这时用到了定位position,right:200px这条CSS将左列往左推了200px,也就是它自己的宽度

1
2
3
4
5
6
7
8
9
#container .columns {
float: left;
position: relative;
}
#left {
width: 200px;
margin-left: -100%;
right: 200px; /* 自身宽度 */
}

STEP 4: PULL THE RIGHT COLUMN INTO PLACE

由于左侧列离开了原来的位置,右列就会自然而然的流过去占据以前左列的位置,那现在怎么把右侧移到它该去的位置呢?(预留的padding-right:150px)同样使用负边距

  • 方法一:与操作左列一样, margin-left: -100%后会到中间列的最左侧,此时利用定位将右列向右推倒最右边,设置为left:100%,这100%表示中间列的宽度
1
2
3
4
5
#right {
width: 150px;
margin-left: -100%;
left:100%;
}
  • 方法二:使用margin-right,设置为-150px,即右列的宽度;或者设置为-100%,这里100%还是指的container这个div的宽度,也就是中间列的宽度。事实上只要外边距的绝对值大于其自身的宽度即150px均能达到这个效果。
1
2
3
4
5
#right {
width: 150px;
margin-right: -150px; /* 自身宽度 */
//margin-right: -100%;
}

到此就将它们的位置放对了。

STEP 5: DESIGN DEFENSIVELY

如果浏览器窗口缩小,中间列宽度小于左列的话,这个布局在标准浏览器中会垮掉,因此有必要设定一个最小宽度

1
2
3
body {
min-width: 550px; /* 2倍左列宽度+右列宽度 */
}

STEP 6: EQUAL-HEIGHT COLUMNS

此时很容易出现三列不等高的情况,这个问题容易解决,常用的方法是利用内边距比负外边距绝对值大一点

1
2
3
4
#container .column {
padding-bottom: 20010px;
margin-bottom: -20000px;
}

为防止溢出,为外层div添加上

1
2
3
4
5
#container {
padding-left: 200px; /* 左列宽度 */
padding-right: 150px; /* 右列宽度 */
overflow: hidden;
}

实际上当container内容区没有浏览器窗口大的时候页脚也会出现一部分空白,所以在这种情况下若需要页脚们可以讲内容区设置固定高度后再添加页脚

1
2
3
#container .column {
height: 1200px;
}

双飞翼布局

双飞翼这个布局来源于淘宝的页面布局,是源于对页面的形象表达。

第一步 确定结构

1
2
3
4
5
<div class="container">
  <div class="center">中间</div>
  <div class="left">左</div>
  <div class="right">右</div>
</div>

现在的问题是在不改变DOM结构的情况下如何让center展示在中间呢

第二步 基本CSS

这时CSS就要发挥其作用了,将container容器定义一个100%的宽度,对其中每个部分,中左右都设置为浮动,这跟圣杯布局中是一样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.container{ 
width:100%;
}
.center {
float:left;
width:100%;
}
.left {
float:left;
width:200px;
}
.right {
float:left;
width:150px;
}

此时中间占据了整个宽度,左右两侧自然也被挤下去了。

第三步 确定各列正确位置

左外边距为-100%,在浮动情况下,负外边距会导致div上移,而使用-100%可以确保它移动到最左侧。对右侧也设置该属性,值为-150px,注意负外边距一定等于该div的宽度才会刚好在最右侧

1
2
3
4
5
6
.left { 
margin-left:-100%;
}
.right {
margin-left:-150px; /* 自身宽度 */
}

注意这里和圣杯布局的区别,圣杯布局是将右侧的属性设定为右外边距,原因在于在圣杯布局中,一开始我们将是希望左右列占据的宽度作为container这个div的内边距去填充的,而在双飞翼布局中,并没有给container设置padding属性,也就是说到目前为止container的内容区宽度(不包括padding、margin和border)占据了整个浏览器视口。细心的同学可能发现了,中间文本去哪了呢?接下来就解决这个问题

第四步 让中间列正确显示

经过上述的设置,中间列两侧的内容会被左右两列给挡住,为了解决这个问题,下面是淘宝的做法:

1、DOM结构的改变:在.center下再次添加一个class=”wrap”的容器

1
2
3
4
5
6
7
<div class="container">
  <div class="center">
   <div class="wrap">中间</div>
</div>
  <div class="left">左</div>
  <div class="right">右</div>
</div>

2、利用CSS调整wrap的位置,就是把左右被挡住的部分,设置为wrap这个div的左、右外边距即可,最终的CSS如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.container { 
width:100%;
}
.container .center {
float:left;
width:100%;
}
.container .center .wrap {
margin-left:200px; /*大于等于左侧宽度*/
margin-right:150px; /*大于等于右侧宽度*/
}
.left {
float:left;
width:200px;
margin-left:-100%;
}
.right {
float:left;
width:150px;
margin-left:-150px;
}

到此已实现了基本功能,等高柱也可以按圣杯布局中同样的方法设定,至于样式上的调整此处不再赘述。

总结

事实上,圣杯布局其实和双飞翼布局是一回事。它们实现的都是三栏布局,两边的盒子宽度固定,中间盒子宽度自适应。它们实现的效果是一样的,差别在于其实现的过程与思想。实际应用中还应灵活使用,根据需要调整。

参考

圣杯布局

双飞翼布局