前言
突然有一天,脑之里不知怎地蹦出一个词,「双飞翼」,这是很久以前的淘宝提出的一种三栏布局优化方案,然而,时间久了已经不记得(换句话说是不理解)为啥要提出这个布局了,昨天在 SF 上发起了一个提问,但良久未有人答复,幸得@王能全是谁 提醒,终于回想起「双飞翼」的完整意义了。谨以此文同大家分享这段心路历程。
圣杯 & 双飞翼
说到「双飞翼」就不得不提及「圣杯」,两者均为三栏布局的优化解决方案如下图
常规情况下,我们的布局框架使用以下写法,从上到下,从左到右。
main
问题倒是没什么问题,然而,如果我们希望中部 main 部分优先显示的话,是可以做布局优化的。
因为浏览器渲染引擎在构建和渲染渲染树是异步的(谁先构建好谁先显示),那么将
部分提前即可优先渲染。
main
于是乎,国外的前辈就提出了「圣杯」布局,目的就是通过 css 的方式配合上面的 DOM 结构,优化 DOM 渲染。
我们来简要地了解一下「圣杯」布局,这不是重点。
圣杯布局
demo :https://jsfiddle.net/zwwill/px57xzp4/
/* 以下为简码,仅保留关键部分 */
header,footer {height: 50px;}
.wrapper {padding:
0 100px 0 100px; overflow:hidden;}
.col {position: relative; float: left;}
.main {width: 100%;height: 200px;}
.left {width: 100px; height: 200px; margin-left: -100%;left: -100px;}
.right {width: 100px; height: 200px; margin-left: -100px; right: -100px;}
使用了 relative相对定位
、 float
(需要请浮动,此处使用 overflow:hidden;
方法)和 负值margin
,将 left 和 right 部分「安装」到 wrapper
的两侧,顾名「圣杯」。具体的思路我就不再做赘述了,网上到处都是解释。
圣杯有问题
当然,正常情况下是没有问题的,但是特殊情况下就会暴露此方案的弊端,如果将浏览器无线变窄,「圣杯」将会「破碎」掉。如图,当 main
部分的宽小于 left
部分时就会发生布局混乱。

于是,淘宝软对针对「圣杯」的缺点做了优化,并提出「双飞翼」布局。
双飞翼布局
demo :https://jsfiddle.net/zwwill/5xjyeu9d/
同样的我们来看简码
header
footer
/* 以下为简码,仅保留关键部分 */
header,footer {height: 50px;}
.wrapper {padding: 0; overflow:hidden;}
.col {float: left;}
.main {width: 100%;}
.main-wrap {margin: 0 100px 0 100px;height: 200px;}
.left {width: 100px; height: 200px; margin-left: -100%;}
.right {width: 100px; height: 200px; margin-left: -100px;}
同样使用了 float
和 负值margin
,不同的是,并没有使用 relative相对定位
而是增加了 dom 结构,增加了一个层级。确实解决了圣杯布局的缺陷。

为什么要设计「双飞翼」布局
双飞翼布局表面上看是很优秀,但是细细想来,为什么要多加一层 dom 树节点,这岂不是增加了 css 样式规则表和 dom 树合并成布局树的计算量吗?
好像绝对定位也可以解决这个问题
细想想,我们可以使用绝对布局,将左右侧边栏定位到到两侧啊?好像也不会出现圣杯布局的毛病?
demo :https://jsfiddle.net/zwwill/awwkpwbL/
header