基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

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 的计算相对简单,它是按照比例分配剩余空间。

  1. 计算总 Grow 值Sum(grow)=所有项目的 flex-grow 之和Sum(grow) = \text{所有项目的 flex-grow 之和}
  2. 计算每个项目分得的空间
    分得空间=剩余空间×当前项目的 flex-growSum(grow)\text{分得空间} = \text{剩余空间} \times \frac{\text{当前项目的 flex-grow}}{\text{Sum(grow)}}
  3. 最终尺寸 = flex-basis + 分得空间

示例

  • 容器宽度:500px
  • 项目 A:flex-basis: 100px, flex-grow: 1
  • 项目 B:flex-basis: 150px, flex-grow: 2

计算过程:

  1. 剩余空间500(100+150)=250px500 - (100 + 150) = 250\text{px}
  2. 总 Grow1+2=31 + 2 = 3
  3. 分配
    • A 分得:250×(1/3)83.33px250 \times (1 / 3) \approx 83.33\text{px}
    • B 分得:250×(2/3)166.66px250 \times (2 / 3) \approx 166.66\text{px}
  4. 最终宽度
    • A:100+83.33=183.33px100 + 83.33 = 183.33\text{px}
    • B:150+166.66=316.66px150 + 166.66 = 316.66\text{px}

特殊情况:如果所有项目的 flex-grow 之和小于 1(例如 A 是 0.2,B 是 0.3),则剩余空间不会被完全分配,容器会留白。分配量 = 剩余空间 * flex-grow(不除以总和)。


2. flex-shrink 的计算规则(消化溢出空间)

剩余空间 < 0(即溢出)时,flex-shrink 生效。它决定了如何扣除溢出的空间。

关键区别

flex-shrink 不是简单地按比例扣除,而是按“加权”比例扣除
权重 = flex-basis * flex-shrink
这意味着:原本尺寸越大的元素,在收缩时承担的收缩量(绝对像素)越多。这样做是为了防止小元素被缩减到 0 或过小,尽量保持视觉比例。

计算公式

  1. 计算溢出空间(绝对值):溢出=(所有项目 flex-basis 之和)容器尺寸|\text{溢出}| = (\text{所有项目 flex-basis 之和}) - \text{容器尺寸}
  2. 计算总权重 (Weighted Sum)
    总权重=(每个项目的 flex-basis×每个项目的 flex-shrink)\text{总权重} = \sum (\text{每个项目的 flex-basis} \times \text{每个项目的 flex-shrink})
  3. 计算每个项目的收缩比例
    收缩比例=当前项目 flex-basis×当前项目 flex-shrink总权重\text{收缩比例} = \frac{\text{当前项目 flex-basis} \times \text{当前项目 flex-shrink}}{\text{总权重}}
  4. 计算需扣除的尺寸
    扣除量=溢出×收缩比例\text{扣除量} = |\text{溢出}| \times \text{收缩比例}
  5. 最终尺寸 = flex-basis - 扣除量

示例

  • 容器宽度:400px
  • 项目 A:flex-basis: 200px, flex-shrink: 1
  • 项目 B:flex-basis: 300px, flex-shrink: 2

计算过程:

  1. 总基础宽度200+300=500px200 + 300 = 500\text{px}
  2. 溢出空间500400=100px500 - 400 = 100\text{px}
  3. 总权重
    • A 的权重:200×1=200200 \times 1 = 200
    • B 的权重:300×2=600300 \times 2 = 600
    • 总权重:200+600=800200 + 600 = 800
  4. 计算扣除量
    • A 需要扣除:100×(200/800)=25px100 \times (200 / 800) = 25\text{px}
    • B 需要扣除:100×(600/800)=75px100 \times (600 / 800) = 75\text{px}
  5. 最终宽度
    • A:20025=175px200 - 25 = 175\text{px}
    • B:30075=225px300 - 75 = 225\text{px}

注意:如果这里不加权,A 和 B 的 shrink 比例是 1:2,那么 A 扣 33px,B 扣 66px。但在加权算法下,B 因为本身大且 shrink 系数大,承担了更多的压缩任务(75px)。


总结对比

特性 flex-grow (放大) flex-shrink (缩小)
触发条件 容器空间有富余 容器空间不足 (溢出)
计算核心 简单的系数比例 加权比例 (系数 × 基础尺寸)
设计意图 填满空白 防止溢出,同时保护小元素不被过度压缩
总和 < 1 空间不分完,有留白 溢出不扣完,依然溢出

边界限制

无论如何计算,最终尺寸都会受到 min-widthmax-width 的限制。

  • 如果计算出的 flex-shrink 后尺寸小于 min-width,则强制设为 min-width,多出来的溢出量会转嫁给其他元素(如果其他元素还能缩的话)。
00:00
00:00