聊聊爲何淘寶要提出「雙飛翼」佈局

clipboard.png

前言

忽然有一天,腦之裏不知怎地蹦出一個詞,「雙飛翼」,這是好久之前的淘寶提出的一種三欄佈局優化方案,然而,時間久了已經不記得(換句話說是不理解)爲啥要提出這個佈局了,昨天在 SF 上發起了一個提問,但良久未有人答覆,幸得@王能全是誰 提醒,終於回想起「雙飛翼」的完整意義了。謹以此文同你們分享這段心路歷程。javascript

聖盃 & 雙飛翼

說到「雙飛翼」就不得不說起「聖盃」,二者均爲三欄佈局的優化解決方案以下圖css

常規狀況下,咱們的佈局框架使用如下寫法,從上到下,從左到右。html

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

問題卻是沒什麼問題,然而,若是咱們但願中部 main 部分優先顯示的話,是能夠作佈局優化的。前端

由於瀏覽器渲染引擎在構建和渲染渲染樹是異步的(誰先構建好誰先顯示),那麼將<section>main</section>部分提早便可優先渲染。java

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

因而乎,國外的前輩就提出了「聖盃」佈局,目的就是經過 css 的方式配合上面的 DOM 結構,優化 DOM 渲染。git

咱們來簡要地瞭解一下「聖盃」佈局,這不是重點。github

聖盃佈局

demo :https://jsfiddle.net/zwwill/p...segmentfault

<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://jsfiddle.net/zwwill/5...

一樣的咱們來看簡碼

<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 樹合併成佈局樹的計算量嗎?

好像絕對定位也能夠解決這個問題

細想一想,咱們可使用絕對佈局,將左右側邊欄定位到到兩側啊?好像也不會出現聖盃佈局的毛病?

demo :https://jsfiddle.net/zwwill/a...

<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
首發地址:https://github.com/zwwill/blo...

相關文章
相關標籤/搜索