flex-grow 和 flex-shrink
先简单理解一下三个概念:
-
flex-basis :Flex 布局引擎在分配空间时,会先计算所有子元素的 flex-basis 之和(如果没有设置,通常就是元素的 width/height 或内容本身的尺寸)。
-
剩余空间(Positive Free Space):当容器宽度 大于 子元素 flex-basis 总和时,多出来的空间。
-
溢出空间 / 负空间(Negative Free Space):当容器宽度 小于 子元素 flex-basis 总和时,缺少的空间。
👉 核心口诀:
flex-grow 只在有“剩余空间”时生效,用于决定怎么瓜分多出来的空间。
flex-shrink 只在有“溢出空间”时生效,用于决定怎么缩小自己来分摊欠下的空间。
flex-grow:如何“瓜分奖金”
默认值:0。意思是:不管多出来多少空间,我也不放大。
如果有剩余空间,Flex 引擎会按照子元素 flex-grow 的比例来分配。
公式
元素分配到的空间 = 剩余空间 × (该元素的 flex-grow / 所有兄弟元素的 flex-grow 总和)
最终宽度 = flex-basis + 分配到的空间
案例
假设:容器宽度 500px。包含两个子元素 A 和 B。
-
A 的 flex-basis 为 100px,flex-grow 为 1
-
B 的 flex-basis 为 100px,flex-grow 为 3
-
计算剩余空间:500 - (100 + 100) = 300px (这就是要瓜分的奖金)。
-
计算总份数:1 + 3 = 4 份。
-
计算 A 分到的空间:300px × (1 / 4) = 75px。
-
计算 B 分到的空间:300px × (3 / 4) = 225px。
-
得出最终宽度:
-
A = 100 + 75 = 175px
-
B = 100 + 225 = 325px
-
flex-shrink:如何“分摊债务”
它的默认值是 1,意思是“大家一起按比例缩小”。如果设为 0,则表示“宁死不屈,绝不缩小”。
🚨 重点注意: flex-shrink 的计算不是像 flex-grow 那样直接按比例瓜分!它是一个加权计算的过程,权重就是元素的 flex-basis。这是为了:
本身尺寸越大(flex-basis 大)的元素,要承担更多的缩小量(分摊更多的债务)。
所以,它的公式更复杂一点:
公式
-
计算总权重 (Total Weight) = Σ (每个元素的 flex-basis × 该元素的 flex-shrink)
-
计算元素的收缩因子 (Shrink Factor) = (该元素的 flex-basis × 该元素的 flex-shrink) / 总权重
-
元素被扣除的空间 = 溢出空间 (绝对值) × 该元素的收缩因子
最终宽度 = flex-basis - 被扣除的空间
要理解这个公式很简单。想象如果不加权,那第二步里分母应该就是 flex-shrink 的求和。
而这里为了加权,所以在此基础上多乘了一个 flex-basis 罢了。
案例
假设:容器宽度 400px。包含两个子元素 A 和 B。
-
A 的 flex-basis 为 200px,flex-shrink 为 1
-
B 的 flex-basis 为 300px,flex-shrink 为 2
-
计算溢出空间:(200 + 300) - 400 = 100px (这就是要分摊的债务)。
-
计算总权重:(A的200 × 1) + (B的300 × 2) = 200 + 600 = 800。
-
计算 A 扣除的空间:100px × (200 / 800) = 25px。
-
计算 B 扣除的空间:100px × (600 / 800) = 75px。
-
得出最终宽度:
-
A = 200 - 25 = 175px
-
B = 300 - 75 = 225px
-
(你可以看到,虽然 B 的 shrink 只是 A 的 2倍,但因为 B 本身更大,它实际被扣除的空间是 A 的 3倍)
常见的实战问题
flex: 1 是什么?
这其实是一个简写属性,是 flex-grow、flex-shrink 和 flex-basis 的简写。
flex: 1 等同于 flex: 1 1 0%
这意味着元素会占据剩余空间(grow: 1),也会收缩(shrink: 1),最重要的是它的基础尺寸被视为 0。这意味着所有容器空间都被当做“剩余空间”来按比例绝对平分,不受元素内部内容本身宽度的影响。
所以,经常用这个属性来分配子元素在父元素中占据的空间比例。
flex-shrink 没生效,元素还是被撑破了
根据 CSS 规范,Flex items 有一个默认的最小尺寸规则:min-width: auto(如果是横向)。
即使你允许元素 shrink,引擎在计算时,它的缩小极限默认就是它内部内容的最小宽度(min-content)。如果不换行文本太长,min-content 就很大,它就缩不下去。
解决办法:
给这个子元素强行加上 min-width: 0; 或者 overflow: hidden;。这就打破了 min-width: auto 的限制,允许子元素缩小到比其内容还要小,配合 text-overflow: ellipsis 就能实现完美的文字截断。
- 标题: flex-grow 和 flex-shrink
- 作者: 三葉Leaves
- 创建于 : 2026-03-09 00:00:00
- 更新于 : 2026-03-16 12:05:06
- 链接: https://blog.oksanye.com/9f4dbe90ccca/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。