面試題:圣杯布局,雙飛翼布局了解嗎

【布局】聊聊為什么淘寶要提出「雙飛翼」布局
圣杯 & 雙飛翼
說到「雙飛翼」就不得不提及「圣杯」,兩者均為三欄布局的優(yōu)化解決方案如下圖
常規(guī)情況下,我們的布局框架使用以下寫法,從上到下,從左到右。
<header>header</header>
<section>
<aside>left</aside>
<section>main</section>
<aside>right</aside>
</section>
<footer>footer</footer>
問題倒是沒什么問題,然而,如果我們希望中部 main 部分優(yōu)先顯示的話,是可以做布局優(yōu)化的。
因為瀏覽器渲染引擎在構(gòu)建和渲染渲染樹是異步的(誰先構(gòu)建好誰先顯示),那么將<section>main</section>部分提前即可優(yōu)先渲染。
<header>header</header>
<section>
<section>main</section>
<aside>left</aside>
<aside>right</aside>
</section>
<footer>footer</footer>
于是乎,國外的前輩就提出了「圣杯」布局,目的就是通過 css 的方式配合上面的 DOM 結(jié)構(gòu),優(yōu)化 DOM 渲染。
我們來簡要地了解一下「圣杯」布局,這不是重點(diǎn)。
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>
/* 以下為簡碼,僅保留關(guān)鍵部分 */
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; 方法)和 負(fù)值 margin ,將 left 和 right 部分「安裝」到 wrapper 的兩側(cè),顧名「圣杯」。
具體的思路我就不再做贅述了,網(wǎng)上到處都是解釋。
圣杯有問題
當(dāng)然,正常情況下是沒有問題的,但是特殊情況下就會暴露此方案的弊端,如果將瀏覽器無線變窄,「圣杯」將會「破碎」掉。如圖,當(dāng) main 部分的寬小于 left 部分時就會發(fā)生布局混亂。
于是,淘寶軟對針對「圣杯」的缺點(diǎn)做了優(yōu)化,并提出「雙飛翼」布局。
雙飛翼布局
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>
/* 以下為簡碼,僅保留關(guān)鍵部分 */
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 和 負(fù)值 margin,不同的是,并沒有使用 relative 相對定位 而是增加了 dom 結(jié)構(gòu),增加了一個層級。確實解決了圣杯布局的缺陷。
為什么要設(shè)計「雙飛翼」布局
雙飛翼布局表面上看是很優(yōu)秀,但是細(xì)細(xì)想來,為什么要多加一層 dom 樹節(jié)點(diǎn),這豈不是增加了 css 樣式規(guī)則表和 dom 樹合并成布局樹的計算量嗎?
好像絕對定位也可以解決這個問題
細(xì)想想,我們可以使用絕對布局,將左右側(cè)邊欄定位到到兩側(cè)啊?好像也不會出現(xiàn)圣杯布局的毛???
<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>
/* 以下為簡碼,僅保留關(guān)鍵部分 */
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(不用請浮動)也沒有 負(fù)值 margin ,僅僅使用了 absolute 絕對定位,好像更優(yōu)秀呢?
但是細(xì)細(xì)想想,單純的絕對定位有一個問題,「高度不可控」,我們假設(shè),如果 left 部分的高度高于 main ,是不是 left 沒有能力撐起整個 wrapper ?
「四不四」~~!
那么我們再來看看雙飛翼和圣杯的情況
都是下圖。
「應(yīng)戳死聽」~~!
那這么看來,所有的方案都或多或少存在一些問題。綜合來看,不管 left, main, right 的大小高低如何,「雙飛翼」布局都能正常顯示,嗯~~確實很優(yōu)秀。
錘子和釘子
綜上所見,「雙飛翼」布局更勝一籌。但是,這是一個「錘子和釘子」的問題,我們應(yīng)該拿著釘子找錘子,而不是拿著錘子找釘子,因為,當(dāng)你有了最大的錘子,看到什么都是釘子。
唉~,我又在裝逼了。\( ̄︶ ̄)/
說白了,就是,對癥下藥,沒有最好的方案,只有最適合的。關(guān)于三欄布局,我?guī)痛蠹伊谐鲆粋€對照表,以便大家快速選擇。






