圣杯布局和双飞翼布局实现两侧宽度固定,中间宽度自适应及其他扩展实现
前沿简介
圣杯布局和双飞翼布局是前端重要的布局方式。两者的功能相同,都是为了实现一个两侧宽度固定,中间宽度自适应的三栏布局。
圣杯布局来源于文章In Search of the Holy Grail,双飞翼布局来源于淘宝UED。
两者的实现方式有差异,但是都遵循以下几点:
- 两侧宽度固定,中间宽度自适应
- 中间部分在DOM结构上优先,以便先行渲染
- 允许三列中的任意一列称为最高列
- 只需要使用一个额外的标签
圣杯布局
DOM结构
主体由
container
包裹center、left、right
三部分,其中的center
在最前面,优先渲染。CSS代码
假设左侧固定宽度200px,右侧固定宽度150px,在
container
上设置如下样式:#container { padding-left: 200px; padding-right: 150px; }
目的就是给左侧以及右侧预留出空间,得到如下示意图:
随后为左中右三列设置浮动与对应的宽度,同时为底部footer设置清除浮动。
#container .column { float: left; } #center { width: 100%; } #left { width: 200px; } #right { width: 150px; } #footer { clear: both; }
得到如下示意图效果:
由于
center
设置了宽度100%,所有左侧left
跟右侧right
被挤到了第二行。如果要把
left
放到预留的位置,那么需要使用负外边距
,代码如下:#left { width: 200px; margin-left: -100%; }
得到如下示意图效果:
由于
margin-right: -100%
占据叠到了center
列左侧,那么需要用定位并且设置right的值为left
列的宽度才能放到左侧预留的位置,代码如下:#left { width: 200px; margin-left: -100%; position:relative; right: 200px; }
这样后得到的示意图效果:
接下来对
right
列进行设置,代码如下:#right { width: 150px; margin-right: -150px; }
最终的示意图效果:
到这儿页面的基本样式完成。但是我们需要考虑
页面的最小宽度
,由于两侧有个固定宽度,感觉最小宽度就是200+150=350px,但是由于left
列使用了定位position:relative
,所以center
列至少有个left
设置的right值的宽度,即200px,所以最终的最小宽度是:200+150+200=550px。body { min-width: 550px; }
那么圣杯布局的整体CSS代码如下:
body { min-width: 550px; } #container { padding-left: 200px; padding-right: 150px; } #container .column { float: left; } #center { width: 100%; } #left { width: 200px; margin-left: -100%; position: relative; right: 200px; } #right { width: 150px; margin-right: -150px; } #footer { clear: both; }
为了看到效果,贴一个完整示例代码,有模块的背景色:
圣杯布局 中间内容左侧内容右侧内容双飞翼布局
DOM结构
双飞翼布局的DOM结构与圣杯布局的区别是用
container
仅包裹住center
,另外将.column
类从center
移至container
上。CSS代码
跟前面思路一样,设置各列宽度与浮动,为左右两列预留出空间,以及底部
footer
清除浮动,代码如下:#container { width: 100%; } .column { float: left; } #center { margin-left: 200px; margin-right: 150px; } #left { width: 200px; } #right { width: 150px; } #footer { clear: both; }
将
left
放到预留位置左侧:#left { width: 200px; margin-left: -100%; }
将
right
放到预留位置右侧:#right { width: 150px; margin-left: -150px; }
最终计算页面的最小宽度:200+150=350px;虽然左侧没有用到定位,但是如果页面的宽度小于350px,那么会挤占中间
center
的宽度,故设置页面最小宽度为500px,代码如下:body { min-width: 500px; }
双飞翼布局的完整CSS代码:
body { min-width: 500px; } #container { width: 100%; } .column { float: left; } #center { margin-left: 200px; margin-right: 150px; } #left { width: 200px; margin-left: -100%; } #right { width: 150px; margin-left: -150px; } #footer { clear: both; }
为了看到效果,也贴一个完整示例代码,有模块的背景色:
双飞翼布局 中间内容左侧内容右侧内容扩展实现
如果去掉额外添加的
标签,也能实现相同的布局。DOM结构变化为如下:
基于双飞翼布局的实现思路,只需要在center上做出修改。
1.使用calc()
.column { float: left; } #center { margin-left: 200px; margin-right: 150px; width: calc(100% - 350px); } #left{ width: 200px; margin-left: -100%; } #right { width: 150px; margin-left: -150px; } #footer { clear: both; }
2.使用border-box
.column { float: left; } #center { padding-left: 200px; padding-right: 150px; box-sizing: border-box; width: 100%; }
需要注意的是:由于padding是盒子的一部分,所以padding部分会具有中间栏的背景色,当中间栏高于侧栏时,会出现中间背景色出现在侧栏下面中。
3.使用flex
DOM结构如下:
CSS代码:
#container { display: flex; } #center { flex: 1; } #left { flex: 0 0 200px; order: -1; } #right { flex: 0 0 150px; }
参考地址:
- 《圣杯布局和双飞翼布局的理解与思考》