基于自己理解的翻译,有一些不必要的语句就删除了。
完整原文见:https://alistapart.com/article/holygrail/
一共三列:
- 一列固定宽度的边栏,可以用于导航栏
- 另一列,可以用于谷歌广告或是网络相册
- 中间列是流动的,用于真实内容
原则:
- 有一个流动的中间列和两个固定宽度的边列
- 中间列在源顺序中是第一位的
- 任何列都可以是最长的
- 只需要一个额外的div标签
- 只需要简单的CSS样式
目录
看看代码
为了能够清晰直观地展示,我们采用了非语义的id(center、left、right),在实际应用中,我们推荐使用语义化的id。
语义化semantic没理解是什么意思,大概是可读性强?
<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>
只需要一个额外的<div>
标签作为所有列的容器,样式十分简单。
CSS样式:左列固定宽度200px 右列固定宽度150px
body {
min-width: 550px; /* 2x LC width + RC width */
}
#container {
padding-left: 200px; /* LC width */
padding-right: 150px; /* RC width */
}
#container .column {
position: relative;
float: left;
}
#center {
width: 100%;
}
#left {
width: 200px; /* LC width */
right: 200px; /* LC width */
margin-left: -100%;
}
#right {
width: 150px; /* RC width */
margin-right: -150px; /* RC width */
}
#footer {
clear: both;
}
/*** IE6 Fix ***/
* html #left {
left: 150px; /* RC width */
}
在设置自己的圣杯布局时,只需要对值进行简单替换就可以了。圣杯布局在所有现代浏览器中都适用:Safari, Opera, Firefox,IE6。IE5将需要至少一个盒模型hack。
它是如何实现的
策略很直观,容器<div>
包含一个流动的中间列和两边固定宽度的padding。左边列对齐左边的padding,右边列对齐右边的padding,让整个中间列填满容器的流动宽度。
第一步 搭框架
从header,footer,container开始
<div id="header"></div><div id="container"></div><div id="footer"></div>
接下来我们为container加上padding,就是左右边列的宽度
#container {
padding-left: 200px; /* LC width */
padding-right: 150px; /* RC width */
}
现在布局如下:
第二步 添加列
在有了基本框架以后,我们开始添加列。
<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>
接下来,我们添加合适的宽度,并且设置float。此外,还需要为footer清除浮动,使它可以位于浮动列的底部。
#container .column {
float: left;
}
#center {
width: 100%;
}
#left {
width: 200px; /* LC width */
}
#right {
width: 150px; /* RC width */
}
#footer {
clear: both;
}
注意,center列的100%宽度参照的是container的宽度,排除了padding。
现在所有列都按照顺序对齐了,但因为中间列占用了100%的可用空间,左列和右列在外面。
第三步 把左列移到空白区域
只需要把左列和contianer的padding对齐就可以了。
需要两步:
- 给左列-100%的左margin(100%参照的是container中间的宽度,也就是中间列的宽度)
#left {
width: 200px; /* LC width */
margin-left: -100%;
}
现在左列和中间列重叠了一部分,右列浮动到了左边,如下图所示:
2. 我们设置一个相对位置,和一个偏移量(就是做列的宽度)
#container .columns {
float: left;
position: relative;
}
#left {
width: 200px; /* LC width */
margin-left: -100%;
right: 200px; /* LC width */
}
right
属性将左列推离右边缘200px,即向左移动200px。现在左列已经对齐container的padding了。
第四步 把右列移到空白区域
我们只需要把他从container中,移动到padding中,同样使用负的margin
#right {
width: 150px; /* RC width */
margin-right: -150px; /* RC width */
}
第五步 适应性设计
当浏览器窗口变小,使得中间列比左列小,布局容易被破坏。所以我们在body上设置一个最小宽度。(IE6不会发生这样的情况,也不支持最小宽度)
body {
min-width: 550px; /* 2x LC width + RC width */
}
此外,我们还需要一些变通方法在IE浏览器中。在IE中,负的margin会将左列推得很远(整个浏览器窗口的宽度),因此我们需要把他推回来,距离为右列的宽度。
* html #left {
left: 150px; /* RC width */
}
设置padding
百分比padding会有些困难,但固定padding可以很容易地添加,只要在每列里加一个div
标签。
如果要给左列一个10px的padding,改变如下:
#left {
width: 180px; /* LC fullwidth - padding */
padding: 0 10px;
right: 200px; /* LC fullwidth */
margin-left: -100%;
}
中间列的padding需要一些额外的小技巧。padding加上100%宽度,导致中间列会向外扩展。因此我们需要增加右外边距(等于padding的总和)。此外,因为中间列更宽了,所以左边列需要移动更大的距离,所以需要增加偏移量。
下面是一个例子:每个边列每边增加10px的padding,中间列每边增加20px的padding。
body {
min-width: 630px; /* 2x (LC fullwidth +
CC padding) + RC fullwidth */
}
#container {
padding-left: 200px; /* LC fullwidth */
padding-right: 190px; /* RC fullwidth + CC padding */
}
#container .column {
position: relative;
float: left;
}
#center {
padding: 10px 20px; /* CC padding */
width: 100%;
}
#left {
width: 180px; /* LC width */
padding: 0 10px; /* LC padding */
right: 240px; /* LC fullwidth + CC padding */
margin-left: -100%;
}
#right {
width: 130px; /* RC width */
padding: 0 10px; /* RC padding */
margin-right: -190px; /* RC fullwidth + CC padding */
}
#footer {
clear: both;
}/*** IE Fix ***/
* html #left {
left: 150px; /* RC fullwidth */
}
上下padding可以直接添加,没有其他问题。
等高的列
由One True Layout发展而来,原作者也没有细说,直接看代码吧。
#container {
overflow: hidden;
}
#container .column {
padding-bottom: 20010px; /* X + padding-bottom */
margin-bottom: -20000px; /* X */
}
#footer {
position: relative;
}
给了底部额外的10px padding。
注意:
- 在Opera 8使用
overflow: hidden
会使得所有的列变得巨大,变通方案在One True Layout有提到。 - 在IE中有另一个问题:IE不裁剪container底部列的背景,会溢出到footer。如果你的footer是分开的,或者你的页面足够高就不用担心这个问题。如果不是,你可以添加一个包装器:
<div id="footer-wrapper">
<div id="footer"></div>
</div>
再用相同的方法,就可以使得列等高,并且footer部分不受影响。
* html body {
overflow: hidden;
}
* html #footer-wrapper {
float: left;
position: relative;
width: 100%;
padding-bottom: 10010px;
margin-bottom: -10000px;
background: #fff; /* Same as body
background */
}
还有一件事情
在我的方法中,我介绍了一个非语义化的容器div。我们不希望用一个额外的div
打乱我们完美的代码。一个section
里只用一个div
,不要多也不要少。这个原则在CSS背后是相同的,padding被直接应用于body,不需要任何其他容器。负向的margin拉伸了header和footer,使得他们可以占据完整的空间。
这个布局在上述提到的所有浏览器中都适用,甚至是IE。但是等高列会有问题,这种布局将在非常小的窗口中会失效,请谨慎使用。