在前端布局中,事實上,圣杯布局其實和雙飛翼布局是一回事。它們實現的都是三欄布局,兩邊的盒子寬度固定,中間盒子自適應,也就是我們常說的 固-比-固 布局。它們實現的效果是一樣的,差別在于其實現的思想。
那么下面我們就來分別解析兩種布局,可以在這里看 最終demo
圣杯布局
圣杯布局的出現是來自于a list part上的一篇文章 In Search of the Holy Grail,在西方,圣杯是表達“渴求之物”的意思。那么先看看他怎么實現。
首先看 html 結構
<div class="container">
<div class="main">
<h2>圣杯布局主內容區</h2>
</div>
<div class="left">左邊欄內容區</div>
<div class="right">右邊欄內容區</div>
</div>
既然是讓主內容區 main
自適應寬度,那么 width:100%
,假設我們左、右邊欄區寬度都為200px
,高度是可以自適應的,在這里我們為了直觀,統一設置為 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
這個三個區域。接下來就要給左右邊欄區域騰地方啦
我們讓外層div container
的左右內間距分別等同于左右邊欄的寬度:padding: 0 200px;
,這個時候,依然是豎著一列,別急,我們先讓他們處于同一行位置,怎么做呢,利用 浮動情況下,負邊界值會導致div上移,所以將這個三個區域都增加float:left;
,left區域 margin-left: -100%;
(這個100%實際是main的寬度) 會疊加到 main 區域上方,right 區域margin-left: -200px
(這200px是右邊區域的寬度),也會疊加到 main 區上方。
此時應該是這個樣子:

灰色區域是為left、和right 空出來歸位的區域。
而我們的css應該是這樣:
/* ------ 圣杯布局同行層疊狀態 ------ */
.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 形態
到了這里,相信你已經知道怎么解決div層疊問題了,沒錯就是利用 position
屬性了,給左右欄和父級container
都添加 position: relative;
,然后左邊 left: -200px
,右邊left: 200px
(這里也可以 right:-200px;
),
這個時候就是最終版了, 別忘記了給外層 container
清除浮動。

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

/*---- 雙飛翼布局一行層疊狀態 ---*/
.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;
}
不過,看到我們的展示圖,中間區域的內容區(紫色),被左右區域給覆蓋住了,那這個好辦,給main-content
這個區域來 padding: 0 200px;
,就是左右區域的寬度,最終效果

圖示可以看到,淺灰色區域就是 main-content
區域的 padding
/*---- 雙飛翼布局最終狀態 ---*/
.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;
}
圣杯與雙飛翼的區別
通過上面的實踐,其實你應該看到了,布局實現的效果都是一樣,區別:
- 圣杯的
padding
放在了父層,利用了float
布局、position
定位、margin
負邊距 - 雙飛翼則將
padding
放在了main
內層嵌套的 div上,僅用了float
布局、margin
負邊距
貌似,看起來雙飛翼css更簡單,但多嵌套了一層 html 標簽,也不好說哪個更好了,根據實際需要,靈活應用吧。
那么這種自適應寬度三欄布局的優點有哪些呢,如下:
- 內容與布局分離,main部分自適應寬度,容易在定寬布局和流體布局中切換
- 在瀏覽器上的兼容性非常好,IE5.5以上都支持
- 三列布局位置切換起來非常方便,只要修改他們自身的margin屬性就可以
好了,圣杯雙飛翼布局詳解,至此結束。