# ❓ 弹性盒子中 flex: 0 1 auto 表示什么意思?

.item {
  flex: 0 1 auto;
}
1
2
3

flex 属性是 flex-growflex-shrinkflex-basis 的简写 默认值为 0 1 auto 后两个属性可选

.item {
  /* 一定项目的放大比例 默认值 0 即如果存在剩余空间,也不放大 */
  /* 如果所有项目的的 flex-grow 都为 1 则他们将等分剩余空间(如果有的话) */
  /* 如果有一个项目的 flex-grow 为 2 其他项目都为 1 那么前者占据的剩余空间将比其他项多一倍 */
  flex-grow: 0;

  /* 定义项目的缩小比例 默认值为 1 即空间不足 该项目将缩小 */
  /* 如果所有项目的 flex-shrink 属性都为 1 当空间不足时 都将等比例缩小 */
  /* 如果一个项目的 flex-shrink 属性为 0 其他项目都为 1 则空间不足时 前者不缩小 */
  /* 负值对该属性无效 */
  flex-shrink: 1;

  /* 定义了在分配多余空间之前 项目占据的主轴空间(main size)*/
  /* 浏览器根据这个属性 计算主轴是否有多余空间 它默认为 auto 即项目的本来大小 */
  flex-basis: auto;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 扩展

那么 flex-growflex-shrink 宽度是怎么去计算的呢

请看题 ❓

* {
  padding: 0;
  margin: 0;
}
.container {
  width: 600px;
  height: 300px;
  display: flex;
}
.left {
  flex: 1 2 500px;
  background: red;
}
.right {
  flex: 2 1 400px;
  background: blue;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

那么 left right 分别占据的宽度是多少

# flex-grow

如何分配剩余空间,其值为一个权重(也称扩张因子),默认为 0,剩余空间将会按照这个权重来分配。

举个 🌰

.container {
  width: x;
  display: flex;

  .item1 {
    // 所占据的空间就是
    // x * a / (a + b + c)
    flex-grow: a;
  }

  .item2 {
    // 所占据的空间就是
    // x * b / (a + b + c)
    flex-grow: b;
  }

  .item3 {
    // 所占据的空间就是
    // x * c / (a + b + c)
    flex-grow: c;
  }
}
// 如果
// x = 1000
// a = 1
// b = 2
// c = 3
// then =>
// item1 => width: 1000 * 1 / (1 + 2 + 3) => 166.66
// item1 => width: 1000 * 2 / (1 + 2 + 3) => 333.33
// item1 => width: 1000 * 3 / (1 + 2 + 3) => 500
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

再举个 🌰

.container {
  width: 1000px;
  display: flex;

  .item1 {
    width: 200px;
    flex-grow: a;
  }

  .item2 {
    width: 100px;
    flex-grow: b;
  }
}
// 那么这个时候 flex-grow 怎么算
// 剩余空间:x => (1000 - 200 - 300) => 700
// item1 => width: 200(原有定义的) + 700 * a / (a + b)
// item2 => width: 100(原有定义的) + 700 * b / (a + b)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

注意:如果 (a + b + c + ...) < 1

// 他们会走这样一个逻辑
let num = a + b + c + ...
if (num < 1) num = 1
1
2
3

那么就会变成

// x = 1000
// a = 0.1
// b = 0.2
// 剩余空间:x => (1000 - 100 - 200) => 700
// item1 => width: 200(原有定义的) + 700 * 0.1 / 1
// item2 => width: 100(原有定义的) + 700 * 0.2 / 1
//剩下的空间将不会分配给任何的元素
1
2
3
4
5
6
7

# flex-shrink

如果你觉得 flex-shrink 的计算方式跟 flex-grow 的类似,其实没有那么简单。

我们通过一个 🌰 来说明

.container {
  display: flex;
  width: 500px;

  .item1 {
    flex-shrink: 1;
    width: 100px;
  }

  .item2 {
    flex-shrink: 1;
    width: 200px;
  }

  .item3 {
    flex-shrink: 1;
    width: 300px;
  }
}

// 首先我们要计算 溢出宽度
// 溢出宽度 x => 100(item1) + 200(item2) + 300(item3) - 500(container) => 100
// 计算出收缩总的权重宽度:每个元素收缩的权重为其 flex-shrink 乘以其宽度
// 总权重 y => (item1 shrink)1 * (item1 width)100 + (item2 shrink)2 * (item2 width)200 + (item3 shrink)3 * (item3 width)300 => 1400
// 那么 三个元素收缩宽度
// item1 => (shrink)1 * (x)100 * (width)100 / (y)1400  => 7.14
// item2 => (shrink)2 * (x)100 * (width)200 / (y)1400  => 28.57
// item3 => (shrink)3 * (x)100 * (width)300 / (y)1400  => 64.28
// 那么最终宽度
// item1 => 100 - 7.14 => 92.86
// item2 => 200 - 28.57 => 171.43
// item1 => 300 - 64.28 => 235.72
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

flex-shrink 为负数的话,该怎么计算呢?

// 如上题
// item1 shrink => 0.1
// item2 shrink => 0.2
// item3 shrink => 0.3
// x => 溢出宽度(100 + 200 + 300 - 500)* (0.1 + 0.2 + 0.3) / 1 => 60
// y => 140 (缩小10倍)
// 那么 三个元素收缩宽度
// item1 => (shrink)0.1 * (x)60 * (width)100 / (y)140  => 4.28
// item2 => (shrink)0.2 * (x)60 * (width)200 / (y)140  => 17.14
// item3 => (shrink)0.3 * (x)60 * (width)300 / (y)140  => 38.57
// 那么最终宽度
// item1 => 100 - 4.28 => 95.72
// item2 => 200 - 17.14 => 182.86
// item1 => 300 - 38.57 => 261.43
1
2
3
4
5
6
7
8
9
10
11
12
13
14

同时,类似 flex-growflex-shrink 也会受到 min-width 的影响。

# 扩展题

那么到这里我们回归上面的扩展题,计算出 left right 值。

// 父元素 width => 600
// left flex => 1 2 500
// right flex => 2 1 400
// 由于我们这里指定了 flex-basis 的值 那么 flex-grow 则会被忽略(个人理解)
// 首先我们计算出溢出宽度 x => 500 + 400 - 600 => 300
// 溢出总权重 y => 2 * 500 + 1 *400 => 1400
// left 溢出缩小值 => 2 * 300 * 500 / 1400 => 214.28
// right 溢出缩小值 => 1 * 300 * 400 / 1400 => 85.72
// left => 500 - 214.28 => 285.72
// right => 400 - 85.71 => 314.28
1
2
3
4
5
6
7
8
9
10

Flex 布局教程:语法篇

详解 flex-grow 与 flex-shrink