在前端布局中,事實上,圣杯布局其實和雙飛翼布局是一回事。它們實現(xiàn)的都是三欄布局,兩邊的盒子寬度固定,中間盒子自適應,也就是我們常說的 固-比-固 布局。它們實現(xiàn)的效果是一樣的,差別在于其實現(xiàn)的思想。
那么下面我們就來分別解析兩種布局,可以在這里看 最終demo
圣杯布局
圣杯布局的出現(xiàn)是來自于a list part上的一篇文章 In Search of the Holy Grail,在西方,圣杯是表達“渴求之物”的意思。那么先看看他怎么實現(xiàn)。
首先看 html 結構
<div class="container">
<div class="main">
<h2>圣杯布局主內容區(qū)</h2>
</div>
<div class="left">左邊欄內容區(qū)</div>
<div class="right">右邊欄內容區(qū)</div>
</div>
既然是讓主內容區(qū) main 自適應寬度,那么 width:100%,假設我們左、右邊欄區(qū)寬度都為200px,高度是可以自適應的,在這里我們?yōu)榱酥庇^,統(tǒng)一設置為 300px,并分別設置不同的背景色,好實際觀測。
這個時候,初步 css 樣式是這樣
/* ------ 圣杯布局初始化 ------ */
.container {}
.container .left {
width: 200px;
height: 300px;
background: #ff8d66;
}
.container .right {
width: 200px;
height: 300px;
background: #7ffe8b;
}
.container .main {
width: 100%;
height: 300px;
background-color:#fcf187;
}
這個時候我們看頁面實際上是豎排列 main left right 這個三個區(qū)域。接下來就要給左右邊欄區(qū)域騰地方啦
我們讓外層div container 的左右內間距分別等同于左右邊欄的寬度:padding: 0 200px;,這個時候,依然是豎著一列,別急,我們先讓他們處于同一行位置,怎么做呢,利用 浮動情況下,負邊界值會導致div上移,所以將這個三個區(qū)域都增加float:left;,left區(qū)域 margin-left: -100%;(這個100%實際是main的寬度) 會疊加到 main 區(qū)域上方,right 區(qū)域margin-left: -200px(這200px是右邊區(qū)域的寬度),也會疊加到 main 區(qū)上方。
此時應該是這個樣子:

灰色區(qū)域是為left、和right 空出來歸位的區(qū)域。
而我們的css應該是這樣:
/* ------ 圣杯布局同行層疊狀態(tài) ------ */
.container {
padding: 0 200px;
}
.container .left {
width: 200px;
height: 300px;
background: #ff8d66;
float: left;
margin-left: -100%;
}
.container .right {
width: 200px;
height: 300px;
background: #7ffe8b;
float: left;
margin-left: -200px;
}
.container .main {
width: 100%;
height: 300px;
background-color:#fcf187;
float: left;
}
圣杯布局——邊欄 relative 形態(tài)
到了這里,相信你已經(jīng)知道怎么解決div層疊問題了,沒錯就是利用 position 屬性了,給左右欄和父級container 都添加 position: relative;,然后左邊 left: -200px,右邊left: 200px(這里也可以 right:-200px;),
這個時候就是最終版了, 別忘記了給外層 container 清除浮動。

/* ------ 圣杯布局區(qū) ------ */
.container {
padding: 0 200px;
overflow:hidden;
zoom:1;
position: relative; /* 相對定位 */
}
.container .left {
width: 200px;
height: 300px;
background: #ff8d66;
float: left;
margin-left: -100%;
position: relative; /* 相對定位 */
left: -200px;
}
.container .right {
width: 200px;
height: 300px;
background: #7ffe8b;
float: left;
position: relative; /* 相對定位 */
left: 200px;
/*right:-200px;*/ /*這里用right偏移方式也可以實現(xiàn)*/
margin-left: -200px;
}
.container .main {
width: 100%;
height: 300px;
background-color:#fcf187;
float: left;
}
圣杯布局——邊欄 absolute 形態(tài)
等等,到這里還沒結束,在上面div層疊狀態(tài)的時候,利用 position: relative; 屬性,
那么你是否想過用 position: absolute; 屬性呢?事實上這里也可以這么做,相對于父級 container-2,
只要讓左區(qū)域 left:0;,右區(qū)域right: 0; 即可:
/* ------ 圣杯布局區(qū) - 形態(tài)二 ------ */
.container-2 {
padding: 0 200px;
overflow:hidden;
zoom:1;
position: relative; /* 相對定位 */
}
.container-2 .left {
width: 200px;
height: 300px;
background: #ff8d66;
position: absolute; /* 絕對定位 */
left:0;
}
.container-2 .right {
width: 200px;
height: 300px;
background: #7ffe8b;
position: absolute; /* 絕對定位 */
right: 0;
}
.container-2 .main {
width: 100%;
height: 300px;
background-color:#fcf187;
position: relative;
float:left;
}
html 結構完全一樣,只是換了個container-2的樣式名,當然具體樣式也有點不同了,但實現(xiàn)效果也一樣。
雙飛翼布局
好,終于到比翼雙飛的時刻了,最終實現(xiàn)的效果肯定和圣杯一樣咯,那么來看html結構,
<div class="wrap">
<div class="main">
<div class="main-content">
<h2>雙飛翼布局主內容區(qū)</h2>
</div>
</div>
<div class="left">左邊欄內容區(qū)</div>
<div class="right">右邊欄內容區(qū)</div>
</div>
這里,外層div換個名字 wrap, 乍一看,和圣杯一樣唄,主要是css實現(xiàn)方式不同。和圣杯一樣,分別設置不同背景色,統(tǒng)一高度,方便觀察。
/*---- 雙飛翼布局初始化 ---*/
.wrap {}
.wrap .left {
width: 200px;
height: 300px;
background: #ccc;
}
.wrap .right {
width: 200px;
height: 300px;
background: #333;
}
.wrap .main {
width: 100%;
height: 300px;
background-color: #666;
}
這個時候,和圣杯布局一樣的預料,豎著排三行。接下來,其實和圣杯的想法一樣,利用 浮動情況下,負邊界值會導致div上移,所以將這個三個區(qū)域都增加float:left;,并給 wrap 清除浮動。
/*---- 雙飛翼布局兩行狀態(tài) ---*/
.wrap {
zoom: 1;
overflow: hidden;
}
.wrap .left {
width: 200px;
height: 300px;
background: #ccc;
float: left;
}
.wrap .right {
width: 200px;
height: 300px;
background: #333;
float: left;
}
.wrap .main {
width: 100%;
height: 300px;
background-color: #666;
float: left;
}
.wrap .main-content {
background: #eee;
}
這個時候,讓left和right移動到和main同行,left區(qū)域需要負100% margin-left: -100%;,這個100%其實就是中間main的寬度,right區(qū)域則只需要負他自己的寬度即可 margin-left: -200px;,現(xiàn)在,三個區(qū)域又處于同一行了

/*---- 雙飛翼布局一行層疊狀態(tài) ---*/
.wrap {
zoom: 1;
overflow: hidden;
}
.wrap .left {
width: 200px;
height: 300px;
background: #ccc;
float: left;
margin-left: -100%;
}
.wrap .right {
width: 200px;
height: 300px;
background: #333;
float: left;
margin-left: -200px;
}
.wrap .main {
width: 100%;
height: 300px;
background-color: #666;
float: left;
}
.wrap .main-content {
background: #eee;
}
不過,看到我們的展示圖,中間區(qū)域的內容區(qū)(紫色),被左右區(qū)域給覆蓋住了,那這個好辦,給main-content這個區(qū)域來 padding: 0 200px;,就是左右區(qū)域的寬度,最終效果

圖示可以看到,淺灰色區(qū)域就是 main-content 區(qū)域的 padding
/*---- 雙飛翼布局最終狀態(tài) ---*/
.wrap {
zoom: 1;
overflow: hidden;
}
.wrap .left {
width: 200px;
height: 300px;
background: #ccc;
float: left;
margin-left: -100%;
}
.wrap .right {
width: 200px;
height: 300px;
background: #333;
float: left;
margin-left: -200px;
}
.wrap .main {
width: 100%;
height: 300px;
background-color: #666;
float: left;
}
圣杯與雙飛翼的區(qū)別
通過上面的實踐,其實你應該看到了,布局實現(xiàn)的效果都是一樣,區(qū)別:
- 圣杯的
padding放在了父層,利用了float布局、position定位、margin負邊距 - 雙飛翼則將
padding放在了main內層嵌套的 div上,僅用了float布局、margin負邊距
貌似,看起來雙飛翼css更簡單,但多嵌套了一層 html 標簽,也不好說哪個更好了,根據(jù)實際需要,靈活應用吧。
那么這種自適應寬度三欄布局的優(yōu)點有哪些呢,如下:
- 內容與布局分離,main部分自適應寬度,容易在定寬布局和流體布局中切換
- 在瀏覽器上的兼容性非常好,IE5.5以上都支持
- 三列布局位置切換起來非常方便,只要修改他們自身的margin屬性就可以
好了,圣杯雙飛翼布局詳解,至此結束。