也许你并不知道 flex-shrink 的计算机制

Flexbox 布局现在已经广泛使用了,我也经常使用。

不过到今天我才知道,原来自己一直以来都有这样一个误区:认为 flex-shrink 的计算机制跟 flex-grow 一样。但其实并不是的。

我们先来看看 flex-grow 的计算机制。

flex-grow

以下面的代码为例:

容器宽度 700px,每个子元素宽度 100px,一共有 3 个子元素。因此,

剩余空间 = 700 - 100 * 3 = 400

也就是说,剩余空间有 400px。接下来就是如何分配这 400px 给 3 个子元素。

首先,计算各项目总的 grow 值:1 + 0 + 3 = 4。

然后按照各个项目的 grow 比例,分配剩余空间:

  • 分配给 .green: 1 / 4 * 400 = 100
  • 分配给 .yellow: 0 / 4 * 400 = 0
  • 分配给 .blue: 3 / 4 * 400 = 300

因此,最终各个项目的宽度如下:

  • .green: 100 + 100 = 200
  • .yellow: 100 + 0 = 100
  • .blue: 100 + 300 = 400

我们来看看是不是这样的:

演示地址:https://codepen.io/zhangbao/pen/LYEZvzZ

果然。

好了,这算回顾一遍 flex-grow 的计算机制了。下面再来看看 flex-shrink 的。

flex-shrink

我再举一个例子,看看 flex-shrink 的情况。

我们先不看最终的呈现效果。先按照 flex-grow 的计算思路计算下 flex-shrink。

错误的计算思路

容器宽度 800px,子元素宽度加起来 900px。就是说两个子元素最终缩减宽度是 900 - 800,也就是 100px。

首先,计算各项目总的 shrink 值:4 + 6 = 10。

然后按照各个项目的 shrink 比例,分配缩减空间:

  • 分配给 .green: 4 / 10 * 100 = 40
  • 分配给 .yellow: 6 / 10 * 100 = 60

因此,最终各个项目的宽度如下:

  • .green: 300 - 40 = 260
  • .yellow: 600 - 60 = 540

好了,我们现在看下实际情况。

演示地址:https://codepen.io/zhangbao/pen/yLyJrEW

伤心了,居然一个是 275px,一个是 525 px。.green 缩减了 25px(而不是 40px),.yellow 缩减了 75px(而不是 60px)!

讲了这些,就是为了说明 flex-shrink 的计算机制跟 flex-grow 并不一样

接下来,我们来看下正确的计算机制是如何的。

正确的计算思路

还是上面的这个例子:

为了计算出每个 Flex 项目的最终宽度。我们需要看几个名词:

  • 项目收缩比例宽度(item shrink scaled width)
  • 总的收缩比例宽度(total shrink scaled width)
  • 收缩比例(shrink ratio)

项目收缩比例宽度

先看公式:

项目收缩比例宽度 = 项目宽度 * 项目的 flex-shrink

就是说:

  • .green 的收缩比例宽度: 300 * 4 = 1200
  • .yellow 的收缩比例宽度: 600 * 6 = 3600

总的收缩比例宽度

先看公式:

总的收缩比例宽度 = 各个项目收缩比例宽度之和

对应本例中的,也就是 1200 + 3600 = 4800。

收缩比例

先看公式:

收缩比例 = 项目收缩比例宽度 / 总的收缩比例宽度

就是说:

  • .green 的收缩比例: 1200 / 4800 = 0.25
  • .yellow 的收缩比例: 3600 / 4800 = 0.75

这里的 0.25 和 0.25 才是真正的项目收缩比例,而不是之前算出的 0.4(4 / 10) 和 0.6(6 / 10)。

最终的项目宽度

知道了 .green 和 .yellow 的收缩比例,还记得总的缩减宽度吧——100px。接下来,就能计算各项目分配的要缩减的宽度了:

  • .green: 100 * 0.25 = 25
  • .yellow: 100 * 0.75 = 75

也就是说:

  • .green 的最终宽度: 300 - 25 = 275
  • .yellow 的最终宽度: 600 - 75 = 525

下面再来看一下这张图,是不是有茅厕顿开的感觉?

参考链接

  • https://github.com/samanthaming/Flexbox30

(完)