圣杯布局和双飞翼布局都是为了实现一个两侧宽度固定,中间宽度自适应的三栏布局。
圣杯布局来源于文章In Search of the Holy Grail,而双飞翼布局来源于淘宝UED。虽然两者的实现方法略有差异,不过都遵循了以下要点:
- 两侧宽度固定,中间宽度自适应
- 中间部分在DOM结构上优先,以便先行渲染
- 允许三列中的任意一列成为最高列
接下来了解一下这两种经典的布局
一、 圣杯布局
下图是圣杯布局的简单模型,左width(200px)右width(200px),中间自适应,三部分保持高度一致。

DOM结构部分
圣杯布局对3个盒子的顺序有一定要求。
middle部分首先要放在container的最前部分,最先渲染,然后是 left 和 right。
<div class="container">
<div class="middle">
<h4>middle</h4>
<p></p>
</div>
<div class="left">
<h4>left</h4>
<p></p>
</div>
<div class="right">
<h4>right</h4>
<p></p>
</div>
</div>
左中右三部分都float布局,中间部分宽度设置为100%,然后利用负边距布局。
负边距布局
让左边的盒子回到最左边:
设置左盒子左边距为-(middle的width),也就是{margin-left:-100%;}。左侧盒子浮动到container内容的最左侧,
但是由于container具有paddding的200px未能浮动到整个container的最左边,再通过绝对定位,使得左侧盒子归位啦。让右边的盒子回到最右边 :
设置右盒子左边距为-(自己的width),也就是{margin-left:-200px;}。这样右盒子将会浮到container内容的最右侧,因为padding依然不是最右边,和上面的左盒子解决方法相似,我们让右侧盒子也归位。
利用父元素的内边距,将三个元素往中间挤。
利用相对定位是的左右部分占据内边距,不会把中间部分的文字覆盖。
三部分分别都加上min-height,使得高度保持一致。
body{
min-width:700px ;//页面缩小造成结构坍塌
}
.container {
overflow: hidden;//清除浮动,让父元素可以抱着子元素
padding: 0 200px;//数值等于左右盒子的width
}
.middle,.left,
.right {
min-height: 200px;//三部分等高度分布
float :left;
position: relative;
}
.middle {
width: 100%;
background: deeppink;
}
.left {
width: 200px;
<!-- 这个元素被挤到中间元素的下面,通过这一属性紧挨container的content部分的最左边,此时与中间部分重合 -->
margin-left: -100%;
background: blue;
<!-- 通过相对定位,使left布局到整个页面的最左侧 -->
left: -200px;
}
.right {
width: 200px ;
<!-- left走了之后,right紧贴着container的content部分的最右边 此时与中间部分重合-->
margin-left: -200px;
background: rgb(204, 255, 20);
<!-- 通过相对定位,使right布局到整个页面的最右侧 -->
right: -200px;
}
二、 双飞翼布局
下面是双飞翼布局的简单模型,三部分main为主要部分,sub和extra相当于鸟的翅膀。三部分都被容器所包裹,main下面还有一个mian-inner容器。

DOM结构部分
3部分的顺序依次是main 、sub 、 extra,详情见下:
<header><h4>内容区</h4></header>
<div class="main">
<div class="main-inner">
<h4>main</h4>
Lorem ipsum dolor sit amet
</div>
</div>
<div class="sub">
<h4>sub</h4>
Lorem ipsum, dolor sit amet
</div>
<div class="extra">
<h4>extra </h4>
Lorem ipsum, dolor sit
</div>
<footer><h4>内容区</h4></footer>
大致思想和圣杯布局一样,main盒子占据100%的宽度,但是主要内容写在main-inner中,通过设置main-inner的margin将左右两侧空出 sub 和 extra 的宽度。
sub 和 extra通过设置负边距,就自动浮动到最左边和最右边。
.main,.sub,
.extra {
float :left;
min-height: 200px;
}
.main {
width: 100%;
background: deeppink;
}
.sub {
width: 200px;
margin-left: -100%;//左边
background: blue;
}
.extra {
width: 200px ;
margin-left: -200px;//右边
background: rgb(204, 255, 20);
}
.main .main-inner {
margin:0 200px;//只是这里的和圣杯布局一开始整个container的padding异曲同工。
min-height: 200px;
background: darkgoldenrod;
word-break: break-all;
}
个人的心得
从以上两种布局中发现,利用负边距可以把挤到下面的盒子在重新布局到主要容器中,布局的位置主要看负边距的宽度,当然前提这些盒子已经脱离文档流。这两种布局的想法就是希望在网页中最重要的部分被最先渲染,这让我对网页设计有了新的认识。