Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【布局】聊聊为什么淘宝要提出「双飞翼」布局 #11

Open
zwwill opened this issue Nov 13, 2017 · 3 comments

Comments

@zwwill
Copy link
Owner

commented Nov 13, 2017

image

前言

突然有一天,脑之里不知怎地蹦出一个词,「双飞翼」,这是很久以前的淘宝提出的一种三栏布局优化方案,然而,时间久了已经不记得(换句话说是不理解)为啥要提出这个布局了,昨天在 SF 上发起了一个提问,但良久未有人答复,幸得@王能全是谁 提醒,终于回想起「双飞翼」的完整意义了。谨以此文同大家分享这段心路历程。

圣杯 & 双飞翼

说到「双飞翼」就不得不提及「圣杯」,两者均为三栏布局的优化解决方案如下图

常规情况下,我们的布局框架使用以下写法,从上到下,从左到右。

<header>header</header>
<section>
    <aside>left</aside>
    <section>main</section>
    <aside>right</aside>
</section>
<footer>footer</footer>

问题倒是没什么问题,然而,如果我们希望中部 main 部分优先显示的话,是可以做布局优化的。

因为浏览器渲染引擎在构建和渲染渲染树是异步的(谁先构建好谁先显示),那么将<section>main</section>部分提前即可优先渲染。

<header>header</header>
<section>
    <section>main</section>
    <aside>left</aside>
    <aside>right</aside>
</section>
<footer>footer</footer>

于是乎,国外的前辈就提出了「圣杯」布局,目的就是通过 css 的方式配合上面的 DOM 结构,优化 DOM 渲染。

我们来简要地了解一下「圣杯」布局,这不是重点。

圣杯布局

demo :https://codepen.io/zwwill/pen/OBYXEa

<template>
<header>header</header>
<section class="wrapper">
    <section class="col main">main</section>
    <aside class="col left">left</aside>
    <aside class="col right">right</aside>
</section>
<footer>footer</footer>
</template>

<style>
/* 以下为简码,仅保留关键部分 */
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;}
</style>

使用了 relative 相对定位float(需要请浮动,此处使用 overflow:hidden; 方法)和 负值 margin ,将 left 和 right 部分「安装」到 wrapper 的两侧,顾名「圣杯」。具体的思路我就不再做赘述了,网上到处都是解释。

圣杯有问题

当然,正常情况下是没有问题的,但是特殊情况下就会暴露此方案的弊端,如果将浏览器无线变窄,「圣杯」将会「破碎」掉。如图,当 main 部分的宽小于 left 部分时就会发生布局混乱。

于是,淘宝软对针对「圣杯」的缺点做了优化,并提出「双飞翼」布局。

双飞翼布局

demo :https://codepen.io/zwwill/pen/oaRLao

同样的我们来看简码

<template>
<header>header</header>
<section class="wrapper">
    <section class="col main">
        <section class="main-wrap">main</section>
    </section>
    <aside class="col left">left</aside>
    <aside class="col right">right</aside>
</section>
<footer>footer</footer>
</template>

<style>
/* 以下为简码,仅保留关键部分 */
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;}
</style>

同样使用了 float负值 margin,不同的是,并没有使用 relative 相对定位 而是增加了 dom 结构,增加了一个层级。确实解决了圣杯布局的缺陷。

为什么要设计「双飞翼」布局

双飞翼布局表面上看是很优秀,但是细细想来,为什么要多加一层 dom 树节点,这岂不是增加了 css 样式规则表和 dom 树合并成布局树的计算量吗?

好像绝对定位也可以解决这个问题

细想想,我们可以使用绝对布局,将左右侧边栏定位到到两侧啊?好像也不会出现圣杯布局的毛病?

<template>
<header>header</header>
<section class="wrapper">
    <section class="col main">main</section>
    <aside class="col left">left</aside>
    <aside class="col right">right</aside>
</section>
<footer>footer</footer>
</template>

<style>
/* 以下为简码,仅保留关键部分 */
header,footer { height: 50px;}
.wrapper { position: relative;}
.main { height: 200px; margin:0 100px;}
.left, .right{ width: 100px; height: 200px; position: absolute; top: 0;}
.left{ left: 0;}
.right{ right: 0;}
</style>

没有使用 float(不用请浮动)也没有 负值 margin ,仅仅使用了 absolute 绝对定位,好像更优秀呢?

但是细细想想,单纯的绝对定位有一个问题,「高度不可控」,我们假设,如果 left 部分的高度高于 main ,是不是 left 没有能力撑起整个 wrapper

「四不四」~~!

那么我们再来看看双飞翼和圣杯的情况

都是下图。

「应戳死听」~~!

那这么看来,所有的方案都或多或少存在一些问题。综合来看,不管 left, main, right 的大小高低如何,「双飞翼」布局都能正常显示,嗯~~确实很优秀。

锤子和钉子

综上所见,「双飞翼」布局更胜一筹。但是,这是一个「锤子和钉子」的问题,我们应该拿着钉子找锤子,而不是拿着锤子找钉子,因为,当你有了最大的锤子,看到什么都是钉子。

唉~,我又在装逼了。 \( ̄︶ ̄)/

说白了,就是,对症下药,没有最好的方案,只有最适合的。关于三栏布局,我帮大家列出一个对照表,以便大家快速选择。

- 优点 缺点
圣杯 结构简单,无多余 dom 层 中间部分宽度小于左侧时布局混乱
绝对定位 结构简单,且无需清理浮动 两侧高度无法支撑总高度
双飞翼 支持各种宽高变化,通用性强 dom 结构多余层,增加渲染树生成的计算量

以上为个人理解,如有不对或可补充之处,还请指点。

另外关于 CSS 布局方案,和前端性能优化部分,移驾一下文章
多行多列类布局方案总结
前端性能优化总结

转载请标明出处
作者:木羽 zwwill
首发地址:#11

@zwwill zwwill added this to the Y-2017 milestone Nov 13, 2017

@zwwill zwwill changed the title 讲讲为什么淘宝要提出「双飞翼」布局 聊聊为什么淘宝要提出「双飞翼」布局 Nov 13, 2017

@zwwill zwwill changed the title 聊聊为什么淘宝要提出「双飞翼」布局 【布局】聊聊为什么淘宝要提出「双飞翼」布局 Dec 1, 2017

@yangbinfx

This comment has been minimized.

Copy link

commented Nov 9, 2018

mark.学到了

@hnscdg hnscdg referenced this issue Nov 27, 2018

Open

圣杯布局和双飞翼布局 #14

3 of 3 tasks complete
@znnnnn

This comment has been minimized.

Copy link

commented Apr 22, 2019

kram

@qqqqqqian

This comment has been minimized.

Copy link

commented May 14, 2019

学习了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.