Flex Box 案例實踐

SamChord發表於2018-11-19
Flex Box 案例實踐

前言

基於前一篇文章關於 Flex 語法知識的梳理,這篇文章整理出一些常見的 Flex 佈局解決方案。實現方式仁者見仁,歡迎大家評論區指正交流。

文中的案例主要包含以下幾個方面:

  • 元素垂直居中佈局
  • 兩欄佈局
  • 三欄佈局

現代瀏覽器都支援 Flex Box 語法,可以放心使用:

Flex Box 案例實踐

正文

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

Flex Box 案例實踐

1.垂直居中

在 Flex 佈局方案出現之前,前端領域要實現元素的垂直居中一直都不是件容易的事。彼時,前端領域也湧現了一大批實現垂直居中的解決方案,這裡簡單回顧一下歷史:

  • 水平居中
    • 行內元素 直接設定 text-align:center;
      就可以了
    • 塊級元素 設定寬高後使用 margin:0 auto;
  • 垂直居中
    • 行內元素(分為單行和多行的情況)

    單行文字可以直接在其父盒子上設定 heightline-height 兩個值相同即可;多行文字可能就需要配合使用 tabletable-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;

}複製程式碼
https://codepen.io/xutaogit/pen/jQwGKJ

上述解決方案是在父容器裡針對子元素做了配置,如果使用子元素本身,有一個 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 意味著該元素放大填充整個空白區域。具體效果如圖示,側邊欄內容再多也只是在元素塊內換行顯示:

Flex Box 案例實踐
  • 不定寬+自適應:理解為兩欄均為自適應寬度。可以做一個假設,主內容區域寬度是側邊欄兩倍,一個可行的方案是:
.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-shrinkflex-basis三個屬性的合併寫法。預設值是:0 1 auto。即元素預設不放大,在容器空間不足時會縮小,內容換行顯示。
上述程式碼即為把容器空白區域等分成三份,側邊欄佔據一份,主內容區域佔據兩份。 視覺效果和上圖類似。

3.三欄佈局

三欄佈局主要是指主體區域內容劃分為三塊,左右兩邊固定寬度,中間內容寬度自適應佈局。

Flex Box 案例實踐

其實在業界有兩個熱門的解決方案:“聖盃佈局”和“雙飛翼佈局”。之所以有不同的叫法只是實現方式不同:

<
!--聖盃佈局結構-->
<
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
}複製程式碼
Flex Box 案例實踐

配合新增headerfooter,而且往往中間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;

}
}複製程式碼
https://codepen.io/xutaogit/pen/jQwGKJ

4.更多參考

Flex Box 案例實踐
Flex Box 案例實踐

以上。

文中案例參考連結

來源:https://juejin.im/post/5bee3192e51d454a9c551b3f

相關文章