# Flex

flex layout 的主要思想是：父容器可以改变（直接）子容器的 width + height + order，以便很好地填充父容器的可用空间而不 overflow。

* 父容器，flex container
* 子容器，flex items

即使子容器的大小是未知的或是动态的，也能很方便地被 lay out 和 align，这就是 “flex” 的含义。

## 1. 相关术语

如果说常规布局是基于 block flow direction 和 inline flow direction，那么 flex 布局就是基于 flex-flow direction。

flex 的子容器是按照 main axis（主轴）或 cross axis（横轴）来进行布局的。

![](https://2598460105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGNkDWo1TzHEOBRUxCRfy%2Fuploads%2FlM987YqOjE7vWrKRDWks%2Fimage.png?alt=media\&token=a7a77937-2831-4943-8d6d-60a92a66a677)

* main axis 是由父容器的 `flex-direction` 属性设置
* cross axis 即垂直于 main axis 的轴
* main size 是子容器的在 main axis 上的 size（width 或 height）
* cross size 是子容器的在 cross axis 上的 size（height 或 width）

flexbox 是单向布局的，要么是 horizontal rows 要么是 vertical columns。

## 2. container 属性

### 2.1 display

`display` 定义了一个 flex container，开启了 flex layout 的上下文。

```css
display: flex;
display: inline-flex;
```

### 2.2 main-axis 和 cross-axis

1. `flex-direction` 建立了 main-axis，即子容器的放置方向
2. `flex-wrap` 表示在 cross-axis 上如何折行
3. `flex-flow` 是 `flex-direction` 和 `flex-wrap` 的缩写
   * 也就是说，它同时定义了 flex container 的 main-axis 和 cross-axis

![](https://2598460105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGNkDWo1TzHEOBRUxCRfy%2Fuploads%2FWad5keAMsdojzmBTa8TJ%2Fimage.png?alt=media\&token=4e5d02c3-d110-4f4f-ae01-91618ac26525)

```css
/* main axis */
flex-direction: row; /* 默认 */
flex-direction: column;
flex-direction: row-reverse;
flex-direction: column-reverse;

/* cross axis */
flex-wrap: nowrap; /* 默认 */
flex-wrap: wrap;
flex-wrap: wrap-reverse;

/* 同时定义 main-axis 和 cross-axis  */
flex-flow: row nowrap; /* flex-direction flex-wrap */
```

### 2.3 分配剩余空间

1. `justify-content` 用来定义父容器如何分配在 main-axis 上的多余空间，即子容器沿 main-axis 的对齐方式
   * `left`, `right`
2. `align-content` 用来分配 lines 在 cross-axis 上的多余空间（仅针对多行时）
   * `normal`（默认）
   * `stretch`

![](https://2598460105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGNkDWo1TzHEOBRUxCRfy%2Fuploads%2FaFBfbZgICXdMJejBJIFb%2Fimage.png?alt=media\&token=1c09aaba-5da5-4781-aa52-4caba199ebda)

公共取值：

* `flex-start`, `flex-end`, `center`：针对 flex-direction（main-axis 时）
* `space-between`, `space-around`, `space-evenly`
* `start`, `end`：针对 writing-mode（main-axis 时）

### 2.4 cross-axis 上的对齐

`align-items` 定义了子容器沿 cross-axis 与同行（或同列）上的兄弟们的对齐方式。

![](https://2598460105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGNkDWo1TzHEOBRUxCRfy%2Fuploads%2FYVLxPNmrKSWgQKUp2y7a%2Fimage.png?alt=media\&token=0110c2f8-7ce2-4b33-a0ef-8cb1b90ae7f2)

取值可以是：

* `stretch`（默认）：拉伸以填充容器
* `flex-start`, `flex-end`, `center`
* `start`, `end`
* `baseline`

### 2.5 gap

1. `row-gap`
2. `column-gap`
3. `gap` 是 `row-gap` 和 `column-gap` 的缩写

```css
gap: 10px;
gap: 10px 30px; /* row-gap column-gap */
row-gap: 10px;
column-gap: 30px;
```

## 3. items 属性

### 3.1 flex

以下属性，设置当父容器在分配剩余空间时，子容器如何“缩”“放”自身的比例。

1. `flex-grow` 设置子容器需要 grow 时的比例
2. `flex-shrink` 设置子容器需要 shrink 时的比例
3. `flex-basis` 设置子容器的 size
   * 当值是 0 时，表示不考虑周围的额外空间
   * 当是其它值时，表示（在父容器给分配空间之前）的默认 size
4. `flex` 是 `flex-grow`, `flex-shrink`, `flex-basis` 的缩写（推荐）

```css
flex-grow: 0;     /* 默认，负值无效 */
flex-shrink: 1;   /* 默认，负值无效 */
flex-basis: auto; /* 默认 */

/* 缩写 */
flex: 0 1 auto;   /* 默认 */
```

![](https://2598460105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGNkDWo1TzHEOBRUxCRfy%2Fuploads%2FVUKuLvLowACCwdI1uYIo%2Fimage.png?alt=media\&token=62c0ea64-0ed0-4fd1-a26d-9c2f2f48faaf)

### 3.2 cross-axis 上的对齐

设置当前子容器沿 cross-axis 与同行（或同列）上的兄弟们的对齐方式。

其值会覆盖父容器设置的 [`align-items`](#2.4-crossaxis-shang-de-dui-qi)。

### 3.3 order

设置子容器的顺序，默认值是 0。

当值相等时，就按照元素在 HTML 代码里的出现顺序进行排列。

```css
order: 0;  /* 默认 */
order: -1;
order: 3;
```

## 4. 主要参考

<https://css-tricks.com/snippets/css/a-guide-to-flexbox/>
