還在為垂直居中苦惱?CSS 佈局利器 flexbox 輕輕鬆鬆幫你搞定
阿新 • • 發佈:2019-08-12
傳統的 CSS 佈局方式是基於**盒模型**(它是根據盒子與父盒子以及兄弟盒子的關係確定**大小**和**位置**的演算法),實現時依賴於 *block*, *inline*, *table*, *position*, *float* 這些屬性,但對於一些特殊佈局不易實現,比如**垂直居中**。
**Flexbox Layout** 是一種新的佈局方式,被稱為**彈性佈局**,它使得子元素(*items*)可以靈活的、響應式的適應父容器(*flex container*)的空間,即使子元素的大小未知或是動態,並且可以很容易實現元素的水平和垂直對齊。
盒模型是基於 **block** 和 **inline** 的流動方向進行佈局,而 **flex 佈局**則是基於彈性流方向(**flex-flow directions**),基本思想如下圖所示。
![flex-direction-terms.svg](https://img2018.cnblogs.com/blog/1424165/201908/1424165-20190810220816710-1302494784.png)
flex 容器內的子元素會沿著 **main axis**(從 **main-start** 到 **main-end** )或 **cross axis**(從 **cross-start** 到 **cross-end**)進行佈局,其中:
- **main axis** - **主軸**,子元素排列的基本軸,要**注意**,它不一定是水平的,這取決於 **flex-direction** 屬性的配置
- **main-start | main-end** - 子元素從 main-start 開始到 main-end 彈性的放置在容器中,預設都在一行排列,**不換行**, 除非設定 **flex-wrap** 屬性
- **main size** - 子元素的**主尺寸**,如果主軸是水平的,那 *width* 是主尺寸;垂直的,那 *height* 是主尺寸
- **cross axis** - 垂直於主軸的軸,稱之為**交叉軸**,方向取決於主軸的方向
- **cross-start | cross-end** - 當子元素**換行時**,每行則從 cross-start 開始到 cross-end 排列
- **cross size** - 與 main size 同理,只不過剛好相反
# Flex Container
使用以下程式碼就可以將一個 HTML 元素指定為 **flex 佈局**:
```css
.container {
display: flex; /* or inline-flex */
}
```
這個元素稱為 **Flex Container**,內部其他 HTML 元素被稱為 **Flex Items**。**flex 容器** 有 6 個屬性:
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- align-items
- align-content
## flex-direction
![flex-direction.svg](https://img2018.cnblogs.com/blog/1424165/201908/1424165-20190810220843363-1765397213.png)
**確定主軸的方向**,也就是內部元素的彈性排列方向。如果不考慮換行,Flexbox 是**單向佈局**的概念,始終將元素放置在**水平行**或**垂直列**中。
```css
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
```
- row(預設): 主軸為水平方向,從左到右排列
- row-reverse: 主軸為水平方向,從右到左排列
- column: 主軸為垂直方向,從上到下排列
- column-reverse: 主軸為垂直方向,從下到上排列
## flex-wrap
![flex-wrap.svg](https://img2018.cnblogs.com/blog/1424165/201908/1424165-20190810220859316-1822917777.png)
預設情況下,子元素不會換行,只會在同一行(或列)中放置,可以使用此屬性**設定換行**。
```css
.container{
flex-wrap: nowrap | wrap | wrap-reverse;
}
```
- nowrap (預設): 不換行
- wrap: 換行,第一行在上方
- wrap-reverse: 換行,第一行在下方
## flex-flow
它是 flex-direction 和 flex-wrap 屬性的縮寫.
```css
flex-flow: <'flex-direction'> || <'flex-wrap'>
```
預設是: `flex-flow: row nowrap`
## justify-content
![justify-content.svg](https://img2018.cnblogs.com/blog/1424165/201908/1424165-20190810220924362-127493445.png)
定義子元素在**主軸上的對齊方式**。
```css
.container {
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
}
```
- flex-start (**預設**): 左對齊,以主軸的起點對齊
- flex-end: 右對齊,以主軸的終點對齊
- center: 居中,以主軸的中點對齊
- space-between: 兩端對齊,子元素間隔相等
- space-around: 子元素兩側的間隔相等,因此,元素之間的間隔正好是與邊框間隔的兩倍
- space-evenly: 子元素分佈排列,並且兩個元素的間隔與到邊框的間隔相等
## align-items
![align-items.svg](https://img2018.cnblogs.com/blog/1424165/201908/1424165-20190810220939935-660491201.png)
定義子元素在**交叉軸上如何對齊**。
```css
.container {
align-items: stretch | flex-start | flex-end | center | baseline;
}
```
- stretch (**預設值**): 如果子元素沒有指定高度或設為 auto,將會拉伸佔滿容器的高度
- flex-start: 以交叉軸的起點對齊
- flex-end: 以交叉軸的終點對齊
- center: 以交叉軸的中點對齊
- baseline: 以子元素的第一行文字的基線對齊
## align-content
![align-content.png](https://img2018.cnblogs.com/blog/1424165/201908/1424165-20190810220955032-2050560065.png)
定義容器內部多行元素的**行對齊方式**,類似於 **justify-content** 定義主軸內**元素的對齊方式**。
**注意: **當只有一行元素時,此屬性不生效
```css
.container {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
```
- stretch (**預設值**):每行拉伸佔滿整個交叉軸
- flex-start:以交叉軸的起點對齊
- flex-end:以交叉軸的終點對齊
- center:以交叉軸的中點對齊
- space-between:在交叉軸上兩端對齊,每行間隔相等
- space-around:每行兩側的間隔相等,因此,行間隔正好是與邊框間隔的兩倍
# Flex Items
Flex 容器內部的子元素也有 6 個屬性,分別是:
- order
- flex-grow
- flex-shrink
- flex-basis
- flex
- align-self
## order
![order.png](https://img2018.cnblogs.com/blog/1424165/201908/1424165-20190810221020401-462493865.png)
預設情況下,元素按**原始順序**排列,但是該屬性可以控制元素在 Flex 容器中的顯示順序,數值越小,越靠前,預設為 0。
```css
.item {
order: