Flex Box 案例實踐

前言
基於前一篇文章關於 Flex 語法知識的梳理,這篇文章整理出一些常見的 Flex 佈局解決方案。實現方式仁者見仁,歡迎大家評論區指正交流。
文中的案例主要包含以下幾個方面:
- 元素垂直居中佈局
- 兩欄佈局
- 三欄佈局
現代瀏覽器都支援 Flex Box 語法,可以放心使用:

正文
在開始之前,還是把這張圖貼上,著重理解 Flex Box
裡主軸( main axis
)和交叉軸( cross axis
)的概念。

1.垂直居中
在 Flex 佈局方案出現之前,前端領域要實現元素的垂直居中一直都不是件容易的事。彼時,前端領域也湧現了一大批實現垂直居中的解決方案,這裡簡單回顧一下歷史:
- 水平居中
text-align:center; margin:0 auto;
- 垂直居中
- 行內元素(分為單行和多行的情況)
單行文字可以直接在其父盒子上設定
height
和line-height
兩個值相同即可;多行文字可能就需要配合使用table
和table-cell
的方式,或者新增偽元素佔位填充的方式實現。- 塊級元素(分為固定寬高和寬高不定的情況)
可以藉助絕對定位。固定寬高的情況設定
top:50%; margin-top:-width/2
;寬高不定的設定top:50%;transform: translateY(-50%);
但這些方案現在都可以拋開,直接使用 Flex Box 即可。
藉助 Flex 語法,實現元素的水平垂直居中,在 Flex Box
內即讓元素在主軸( main axis
)和交叉軸( cross axis
)上分別居中。語法梳理裡整理過, justify-content
定義了元素在主軸方向上的排列方式, align-item
定義了元素在交叉軸上的排列方式,所以一個可行的解決方案即為:
.parent{ display:flex; justify-content:center; align-items:center; } 複製程式碼

align-self
屬性會覆蓋容器的
align-items
屬性,定義其在容器內部交叉軸上的排列方式。所以,另一個可行的解決方案可為:
.parent{ display:flex; justify-content:center; } .child{align-self:center;} 複製程式碼
得到的效果和上面是一樣的,具體可參見:flex-center
2.兩欄佈局
兩欄佈局常見於一些部落格或資訊類網站,分為 固定寬+自適應
和 不定寬+自適應
兩種模式。這裡給出一個基本佈局結構:
<div class="box"> <main>正文內容容</main> <aside>側邊欄內容</aside> </div> 複製程式碼
- 固定寬+自適應:側邊欄固定寬度
200px
,主內容區域自適應;主內容區域結構靠前是為了優先載入顯示,側邊區域可通過設定order
調整。
.box{display:flex} .box aside{width:200px; order:-1;}//設定 order 讓側邊欄前置顯示 .box main{flex-grow:1}//設定 flex-grow:1 會使該板塊填充容器空白空間 複製程式碼
上述程式碼之所以設定 flex-grow:1
能達到填充容器剩餘空間的原因: 側邊欄(aside)預設的 flex-grow:0
表明不放大,同時主內容區域設定為 1 意味著該元素放大填充整個空白區域 。具體效果如圖示,側邊欄內容再多也只是在元素塊內換行顯示:

- 不定寬+自適應:理解為兩欄均為自適應寬度。可以做一個假設,主內容區域寬度是側邊欄兩倍,一個可行的方案是:
.box{display:flex} .box aside{flex:1; order:-1;}//等價於 flex:1 1 0; .box main{flex:2;}//等價於 flex:2 2 0; 複製程式碼
語法篇關於 flex
屬性有提及它是 flex-grow
, flex-shrink
和 flex-basis
三個屬性的合併寫法。預設值是: 0 1 auto
。即元素預設不放大,在容器空間不足時會縮小,內容換行顯示。
上述程式碼即為把容器空白區域等分成三份,側邊欄佔據一份,主內容區域佔據兩份。 視覺效果和上圖類似。
3.三欄佈局
三欄佈局主要是指主體區域內容劃分為三塊,左右兩邊固定寬度,中間內容寬度自適應佈局。

其實在業界有兩個熱門的解決方案:“聖盃佈局”和“雙飛翼佈局”。之所以有不同的叫法只是實現方式不同:
<!--聖盃佈局結構--> <div class="content"> <div class="center"></div> <div class="left"></div> <div class="right"></div> </div> <!--雙飛翼佈局結構--> <div class="content"> <div class="center"> <div class="middle"></div> </div> <div class="left"></div> <div class="right"></div> </div> 複製程式碼
聖盃佈局原理:父盒子設定兩個側邊欄寬度需要的 padding
值, center
盒子設定 100%
於父盒子的寬且子盒子均脫離文件左浮動;特別要注意的是因為父盒子設定了 padding
值,子盒子需要設定 relaive
相對於文件然後用負邊距進行定位。
雙飛翼佈局原理: center
盒子內部的 middle
元素設定供給左右兩邊側邊欄寬度的 margin
值, center
盒子設定 100%
於父盒子的寬且子盒子均脫離文件左浮動;然後側邊盒子通過負邊距抵消 middle
盒子內預設的 margin
值進行定位。
具體實現程式碼網路上有很多資源,這裡就不展開了。
迴歸到 Flex Box
,發現事情變得簡單很多。我們針對聖盃結構進行佈局(因為雙飛翼佈局需要額外新增一個元素),一個可行的解決方案如下:
<!--左右側邊欄均自適應寬度--> .content{display:flex; height:200px;} .content .left{order:-1; background:#3498db;flex-grow:1;} .content .right{background:#34495e;flex-grow:1;} .content .center{flex-grow:2;background:#e74c3c} <!--左右側邊欄固定寬度--> .content{display:flex; height:200px;} .content .left{order:-1; background:#3498db;width:200px;} .content .right{background:#34495e;width:200px;} .content .center{flex-grow:1;background:#e74c3c} 複製程式碼

配合新增 header
和 footer
,而且往往中間 content
內容需要自適應高度。基於聖盃佈局結構,可以在外部父盒子設定 flex-direction
做整體垂直方向佈局。 HTML
結構和樣式程式碼可以是:
<div class="container"> <div class="header">This is head</div> <div class="content"> <div class="center">center</div> <div class="left">left</div> <div class="right">right</div> </div> <div class="footer">This is foot</div> </div> 複製程式碼
.container{display:flex; flex-direction:column;min-height:100vh;} //設定容器相對視窗 100% 高度 .header,.footer{flex:1;} .header{background:#1abc9c;} .content{flex:1;display:flex;} .left{order:-1; background:#3498db;flex: 0 0 12em;} .right{background:#34495e;flex: 0 0 10em;} .center{background:#e74c3c;flex:1;} .footer{background:#f1c40f;} 複製程式碼
如果要在移動裝置上顯示效果良好,主體區域內容要改變元素排列方式,可能需要新增 media query
做適配。
@media (max-width: 768px) { .content { flex-direction: column; flex: 1; } .left, .right,.center{ flex: auto; } } 複製程式碼
