用五種方法來聊一聊傳說中的三欄佈局

引言

  三欄佈局是目前網站建設的主流佈局,同時也是面試中必考的一個點,不管是PC端仍是移動端三欄佈局都是很是重要的一個CSS知識點,關於三欄佈局的方案說的最爛的莫過於聖盃佈局了,其主要的核心思想其實就只有一條:實現兩欄固定,中間自適應,保證頁面的佈局不受窗口大小的變化而紊亂。本文總結了五種實現三欄佈局的方法,包括主流的聖盃佈局、雙飛翼佈局,也包含了一些我的遐想的非主流佈局,供同窗們學習和參考。css

1、聖盃佈局

  聖盃佈局的思想是將頁面縱向分爲三個部分,即 header、container、footer,而後又將 container 定爲三欄佈局。在這裏主要講解其中的 container 佈局。html

  首先在 container 裏面有三欄,分別是 left、middle、right,注意這裏 middle 須要放在最前面,保證能夠獲得優先渲染:面試

 1 <div class="grail-container">
 2     <div class="grail-middle">
 3         Grail main
 4     </div>
 5     <div class="grail-left">
 6         Grail left
 7     </div>
 8     <div class="grail-right">
 9         Grail right
10     </div>
11 </div>

  對於 container ,設置一個屬性 overflow: hidden; 讓其造成一個 BFC ,而後使其三欄浮動,並使用相對定位:wordpress

1 .grail-container {
2     overflow: hidden;
3 }
4 .grail-container>div {
5     position: relative;
6     float: left;
7     height: 100%;
8 }

  這時執行如下的步驟:佈局

  ① 置 middle 的 width: 100%,給 left 和 right 定寬度,這裏假設都是 width: 200px;post

  ② 這時 left 被擠到下面去了,因此咱們要把它拉回來,設置 margin-left: -100%;性能

  ③ 還有一個 right 沒有拉回來,一樣,設置 margin-left: 200px;,這裏的長度等於 right 自身的長度學習

  ④ 這時 middle 的兩邊被 left 和 right 給覆蓋了,因而咱們要把兩邊懟回來,設置 container padding: 0 200px 0 200px;flex

  ⑤ middle 懟回來了,但是 left 和 right 也跟着回來,因此如今咱們要把 left 和 right 給懟回去,分別設置 left left: -200px;,right right: -200px;(這就是以前爲何要用相對定位)網站

 1 .grail-container {
 2     overflow: hidden;
 3     padding: 0 200px;
 4 }
 5 .grail-container>div {
 6     position: relative;
 7     float: left;
 8     height: 100%;
 9 }
10 .grail-middle {
11     width: 100%;
12     background-color: blue;
13 }
14 .grail-left {
15     width: 200px;
16     background-color: green;
17     margin-left: -100%;
18     left: -200px;
19 }
20 .grail-right {
21     width: 200px;
22     background-color: brown;
23     margin-left: -200px;
24     right: -200px;
25 }

  聖盃佈局就完成了,不信拖拖看,是否是中間就自適應了?不過它有一個弊端,就是當拖到很小的時候,佈局會亂,因而咱們有了下面的佈局:雙飛翼佈局。

 2、雙飛翼佈局

  雙飛翼佈局使於淘寶,是淘寶團隊提出來的一種實現三欄佈局的方案,其和聖盃佈局是同門兄弟,一樣將頁面分爲 header、container、footer ,不過在 container 裏面有所區別。聖盃佈局的缺陷在於內容區被 container 的 padding 夾在裏面,使得頁面寬度太小時會出現佈局紊亂,這時候雙飛翼佈局就不使用 padding 來將內容區夾在裏面,而是給內容區添加一個 main ,設置 margin 將頁面主動的撐開,其 DOM 結構與聖盃相似,區別在於在 middle 中多了一個 main:

 1 <div class="double-wing-container">
 2     <div class="double-wing-middle">
 3         <div class="double-wing-main">
 4             Double wing main.  
 5         </div>
 6     </div>
 7     <div class="double-wing-left">
 8         Double wing left.  
 9     </div>
10     <div class="double-wing-right">
11         Double wing right
12     </div>
13 </div>
1 .double-wing-container {
2     overflow: hidden;
3 }
4 .double-wing-container>div {
5     position: relative;
6     float: left;
7     height: 100%;
8 }

  這時執行與聖盃佈局相似的步驟:

  ① 置 middle 的 width: 100%,給 left 和 right 定寬度,這裏假設都是 width: 200px;

  ② 這時 left 被擠到下面去了,因此咱們要把它拉回來,設置 margin-left: -100%;

  ③ 還有一個 right 沒有拉回來,一樣,設置 margin-left: 200px;,這裏的長度等於 right 自身的長度

  注意這裏開始就有區別了:

  ④ 使用 main 把內容區撐開,設置 margin: 0 200px 0 200px;,同時設置 overflow: hidden; 使其造成一個 BFC

 1 .double-wing-container {
 2     overflow: hidden;
 3 }
 4 .double-wing-container>div {
 5     position: relative;
 6     float: left;
 7     height: 100%;
 8 }
 9 .double-wing-middle {
10     width: 100%;
11     background-color: gray;
12 }
13 .double-wing-left {
14     width: 200px;
15     background-color: orange;
16     margin-left: -100%;
17 }
18 .double-wing-right {
19     width: 200px;
20     background-color: red;
21     margin-left: -200px;
22 }
23 .double-wing-main {
24     height: 100%;
25     margin: 0 200px;
26     background-color: pink;
27     overflow: hidden;
28 }

  如今再試試,是否是比聖盃佈局稍微好一點,在窗口寬度太小時不會出現排版混亂?其核心就是把內容部分從 middle 遷移到了 main。

  以上兩種佈局方案已經適用於絕大部分場景,若是你只是想找一個三欄佈局的解決方案,那麼到此就夠了。不過,若是你想要的不僅是這些,if you wanna more,那麼就一塊兒來聊一聊下面的佈局方案。

  首先呢,咱們的兩大三欄佈局都有一個固定的模式,那就是兩欄固定,中間自適應,但是你有沒有想過,咱們來實現一個三欄自適應的佈局?那麼大名鼎鼎的 Flex 佈局就登場了,Flex 佈局不光能夠實現兩欄固定,中間自適應,也能夠實現三欄自適應,甚至隨意固定,隨意自適應。

3、Flex 佈局

  Flex 佈局可謂 CSS3 提供一個佈局神奇,將 CSS2 中的許多難點一網打盡。關於 Flex 佈局的語法,這裏就不作討論了,若是有不熟悉的同窗能夠先看看阮老師的文章:Flex 佈局教程:語法篇 這篇文章講解的十分通俗易懂。在這裏咱們先照樣子實現一個三欄佈局, 兩欄固定,中間自適應。

  首先,DOM 結構也是同樣的:

 1 <div class="flex-container">
 2     <div class="flex-middle">
 3         Flex main
 4     </div>
 5     <div class="flex-left">
 6         Flex left
 7     </div>
 8     <div class="flex-right">
 9         Flex right
10     </div>
11 </div>

  而後執行如下步驟:

  ① 設置 container 佈局方式 display: flex; 

  ② 這時候設置 middle width: 100%; ,同時給兩欄定寬,這裏假設都是 width: 200px;

  ③ 既然是兩欄固定,那麼就不讓兩欄收縮,給 left 和 right 設置 flex-shrink: 0;

  ④ 因爲 DOM 結構和咱們實際的順序不同,這時咱們來排個序 left order: 1;,middle order: 2;,right order: 3;

 1 .flex-container {
 2     display: flex;
 3 }
 4 .flex-container>div {
 5     height: 100%;
 6 }
 7 .flex-left {
 8     width: 200px;
 9     background-color: yellow;
10     order: 1;
11     flex-shrink: 0;
12 }
13 .flex-middle {
14     width: 100%;
15     background-color: gray;
16     order: 2;
17 }
18 .flex-right {
19     width: 200px;
20     background-color: red;
21     order: 3;
22     flex-shrink: 0;
23 }

  OK啦,如今拖動試一試。能夠看出 flex 佈局具備更強的適應性,在窗口寬度太小的時候不會形成頁面佈局混亂。經過設置內容的伸縮,能夠實現任意欄的固定和自適應,同時也能夠實現三欄自適應,經過設置 flex 內容的 flex-shrinkflex-grow 能夠實現自定義的適應性佈局。接下來,我們聊一聊一些我的的遐想,偏非主流的三欄佈局。

4、絕對定位佈局

  絕對定位其強大之處在於它的定位性能很是的優秀,這裏咱們就能夠用絕對定位的自動伸縮性來實現一個三欄佈局。

  DOM 結構依然不變:

 1 <div class="absolute-container">
 2     <div class="absolute-middle">
 3         Absolute main
 4     </div>
 5     <div class="absolute-left">
 6         Absolute left
 7     </div>
 8     <div class="absolute-right">
 9         Absolute right
10     </div>
11 </div>

  注意咱們須要將 container 的 postion: relative; ,由於絕對定位元素的參照物爲第一個 postion 不爲 static 的祖先元素,同時須要使 left 向左浮動,right 向右浮動,同時使 middle 絕對定位,並把左右兩邊撐開:

 1 .absolute-container {
 2     position: relative;
 3     overflow: hidden;
 4 }
 5 .absolute-container>div {
 6     height: 100%;
 7 }
 8 .absolute-left {
 9     float: left;
10     width: 200px;
11     background-color: blue;
12 }
13 .absolute-middle {
14     position: absolute;
15     left: 200px;
16     right: 200px;
17     top: 0;
18     bottom: 0;
19     background-color: pink;
20 }
21 .absolute-right {
22     float: right;
23     width: 200px;
24     background-color: brown;
25 }

  注意絕對定位元素的高度須要設 top: 0 bottom: 0 來使其高度撐開。如今試一試是否是一樣也實現了三欄佈局,不過這種佈局方案有一個致命的缺點,就是中間的內容區徹底依賴於兩欄的高度,若是兩欄的高度不夠,那麼中間內容區的高度也會隨着壓縮,因此這種方案在不少場景下並不適合。下面咱們來聊一個較強一點的非主流三欄佈局。

5、table-cell 三欄佈局

   在前三種三欄佈局方案中,咱們三欄的高度取決於各自的內容區,也就是說若是中間內容多,兩邊內容少的狀況下,頁面的高度取決於內容區,同時兩欄的高度不會增長,這是當今絕大多數的網站所採用的主流佈局。第四種方案中的致命缺陷爲中間內容區的高度取決於兩欄的最高點。如今咱們討論一種非主流的三欄佈局方案,表格佈局,使其三欄高度統一,這種佈局方案主要是利用了表格佈局的伸縮性。首先 DOM 結構有所改變,middle 不能放在最前面了:

 1 <div class="table-cell-container">
 2     <div class="table-cell-left">
 3          Table cell left
 4     </div>
 5     <div class="table-cell-middle">
 6          Table cell main
 7     </div>
 8     <div class="table-cell-right">
 9          Table cell right
10     </div>
11 </div>

  這時執行如下步驟:

  ① 將 left、middle、right 都設置爲表格單元 display: table-cell;

  ② 給 left 和 right 定寬,這裏假設 width: 200px;,同時設置 middle width: 100%; 

  ③ 這時候因爲 middle 把兩欄都給擠到兩邊去了,因此這時候咱們要把兩欄給擠回來,設置 min-width: 200px;

 1 .table-cell-container {
 2     position: relative;
 3     overflow: hidden;
 4 }
 5 .table-cell-container>div {
 6     height: 100%;
 7     display: table-cell;
 8 }
 9 .table-cell-left {
10     width: 200px;
11     min-width: 200px;
12     background-color: red;
13 }
14 .table-cell-middle {
15     margin: 0 200px;
16     width: 100%;
17     background-color: brown;
18 }
19 .table-cell-right {
20     min-width: 200px;
21     width: 200px;
22     background-color: yellow;
23 }

  OK ,如今試一試是否是一樣的是一個三欄佈局,並且這種佈局方案中的三欄高度是統一的,可是其缺陷就是 middle 不可以像其餘三欄佈局那樣放在最前面獲得最早渲染。

總結

  三欄佈局的方式其實有不少,不過只要掌握了其核心思想就能夠實現自定義的三欄佈局。聖盃佈局運用的很普遍,不過其致命的缺點就是 middle 區域佔用空間過寬時會把兩欄給擠下去,也就是當窗口 size 太小時,而雙飛翼佈局正是彌補了這一缺點。若是項目不考慮低版本 IE 的兼容性的話,建議仍是使用 Flex  佈局,simple and powerful,若是你想試試新鮮,也能夠嚐嚐表格佈局,你能夠在下面隨意拖動觀察不一樣佈局方案的區別:

References:

  [1] 張鑫旭 . CSS深刻理解流體特徵和BFC特性下多欄自適應佈局

  [2] 阮一峯 . Flex 佈局教程:語法篇

  [3] 張鑫旭 . 我熟知的三種三欄網頁寬度自適應佈局方法

相關文章
相關標籤/搜索