三欄佈局是目前網站建設的主流佈局,同時也是面試中必考的一個點,不管是PC端仍是移動端三欄佈局都是很是重要的一個CSS知識點,關於三欄佈局的方案說的最爛的莫過於聖盃佈局了,其主要的核心思想其實就只有一條:實現兩欄固定,中間自適應,保證頁面的佈局不受窗口大小的變化而紊亂。本文總結了五種實現三欄佈局的方法,包括主流的聖盃佈局、雙飛翼佈局,也包含了一些我的遐想的非主流佈局,供同窗們學習和參考。css
聖盃佈局的思想是將頁面縱向分爲三個部分,即 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 }
聖盃佈局就完成了,不信拖拖看,是否是中間就自適應了?不過它有一個弊端,就是當拖到很小的時候,佈局會亂,因而咱們有了下面的佈局:雙飛翼佈局。
雙飛翼佈局使於淘寶,是淘寶團隊提出來的一種實現三欄佈局的方案,其和聖盃佈局是同門兄弟,一樣將頁面分爲 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 佈局不光能夠實現兩欄固定,中間自適應,也能夠實現三欄自適應,甚至隨意固定,隨意自適應。
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-shrink 和 flex-grow 能夠實現自定義的適應性佈局。接下來,我們聊一聊一些我的的遐想,偏非主流的三欄佈局。
絕對定位其強大之處在於它的定位性能很是的優秀,這裏咱們就能夠用絕對定位的自動伸縮性來實現一個三欄佈局。
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 來使其高度撐開。如今試一試是否是一樣也實現了三欄佈局,不過這種佈局方案有一個致命的缺點,就是中間的內容區徹底依賴於兩欄的高度,若是兩欄的高度不夠,那麼中間內容區的高度也會隨着壓縮,因此這種方案在不少場景下並不適合。下面咱們來聊一個較強一點的非主流三欄佈局。
在前三種三欄佈局方案中,咱們三欄的高度取決於各自的內容區,也就是說若是中間內容多,兩邊內容少的狀況下,頁面的高度取決於內容區,同時兩欄的高度不會增長,這是當今絕大多數的網站所採用的主流佈局。第四種方案中的致命缺陷爲中間內容區的高度取決於兩欄的最高點。如今咱們討論一種非主流的三欄佈局方案,表格佈局,使其三欄高度統一,這種佈局方案主要是利用了表格佈局的伸縮性。首先 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,若是你想試試新鮮,也能夠嚐嚐表格佈局,你能夠在下面隨意拖動觀察不一樣佈局方案的區別:
[1] 張鑫旭 . CSS深刻理解流體特徵和BFC特性下多欄自適應佈局
[2] 阮一峯 . Flex 佈局教程:語法篇
[3] 張鑫旭 . 我熟知的三種三欄網頁寬度自適應佈局方法