flex-grow 和 flex-shrink 的计算规则是怎样的?
flex-grow(放大)和 flex-shrink(缩小)是 CSS Flexbox 布局中两个核心属性,它们的计算方式虽然看似对称,但实际上有着本质的区别,特别是 flex-shrink 引入了“权重”的概念。
以下是详细的计算规则和示例。
前置概念
在计算之前,浏览器首先确定 flex-basis(基础尺寸)。
- 如果有设置
flex-basis且不为 auto,则取该值。 - 如果
flex-basis: auto,则取width的值。 - 如果都没设置,则根据内容大小决定。
我们定义以下变量:
- 剩余空间 (Free Space) = 容器主轴尺寸 - 所有项目
flex-basis之和。
1. flex-grow 的计算规则(瓜分剩余空间)
当 剩余空间 > 0 时,flex-grow 生效。它决定了如何分配这些多出来的空间。
计算公式
flex-grow 的计算相对简单,它是按照比例分配剩余空间。
- 计算总 Grow 值:
- 计算每个项目分得的空间:
- 最终尺寸 =
flex-basis+ 分得空间
示例
- 容器宽度:
500px - 项目 A:
flex-basis: 100px,flex-grow: 1 - 项目 B:
flex-basis: 150px,flex-grow: 2
计算过程:
- 剩余空间:
- 总 Grow:
- 分配:
- A 分得:
- B 分得:
- 最终宽度:
- A:
- B:
特殊情况:如果所有项目的
flex-grow之和小于 1(例如 A 是 0.2,B 是 0.3),则剩余空间不会被完全分配,容器会留白。分配量 = 剩余空间 * flex-grow(不除以总和)。
2. flex-shrink 的计算规则(消化溢出空间)
当 剩余空间 < 0(即溢出)时,flex-shrink 生效。它决定了如何扣除溢出的空间。
关键区别
flex-shrink 不是简单地按比例扣除,而是按“加权”比例扣除。
权重 = flex-basis * flex-shrink。
这意味着:原本尺寸越大的元素,在收缩时承担的收缩量(绝对像素)越多。这样做是为了防止小元素被缩减到 0 或过小,尽量保持视觉比例。
计算公式
- 计算溢出空间(绝对值):
- 计算总权重 (Weighted Sum):
- 计算每个项目的收缩比例:
- 计算需扣除的尺寸:
- 最终尺寸 =
flex-basis- 扣除量
示例
- 容器宽度:
400px - 项目 A:
flex-basis: 200px,flex-shrink: 1 - 项目 B:
flex-basis: 300px,flex-shrink: 2
计算过程:
- 总基础宽度:
- 溢出空间:
- 总权重:
- A 的权重:
- B 的权重:
- 总权重:
- 计算扣除量:
- A 需要扣除:
- B 需要扣除:
- 最终宽度:
- A:
- B:
注意:如果这里不加权,A 和 B 的 shrink 比例是 1:2,那么 A 扣 33px,B 扣 66px。但在加权算法下,B 因为本身大且 shrink 系数大,承担了更多的压缩任务(75px)。
总结对比
| 特性 | flex-grow (放大) | flex-shrink (缩小) |
|---|---|---|
| 触发条件 | 容器空间有富余 | 容器空间不足 (溢出) |
| 计算核心 | 简单的系数比例 | 加权比例 (系数 × 基础尺寸) |
| 设计意图 | 填满空白 | 防止溢出,同时保护小元素不被过度压缩 |
| 总和 < 1 | 空间不分完,有留白 | 溢出不扣完,依然溢出 |
边界限制
无论如何计算,最终尺寸都会受到 min-width 和 max-width 的限制。
- 如果计算出的
flex-shrink后尺寸小于min-width,则强制设为min-width,多出来的溢出量会转嫁给其他元素(如果其他元素还能缩的话)。
右滑查看面试常问