flex-grow按比例分配剩余空间、flex-shrink按加权(flex-shrink×flex-basis)分摊溢出、flex-basis是初始基准且优先级高于width;三者协同决定最终尺寸,缺一易致布局错乱。

flex-grow 和 flex-shrink 不是简单按比例放大缩小,而是基于「剩余空间」和「溢出空间」加权分配的;关键在于它们都依赖 flex-basis 的初始尺寸,且权重计算时会乘以各自的 flex-basis 值 —— 这一点被大量教程忽略,但直接决定最终宽度是否符合预期。
flex-grow 怎么算剩余空间?
它只在父容器有「剩余空间」(即子项总 flex-basis 小于父宽)时生效。计算分三步:
- 先按
flex-basis(或width,若未设flex-basis)确定每个子项的“预约宽度” - 剩余空间 = 父容器主轴尺寸 − 所有子项
flex-basis之和 - 可分配增量 = 剩余空间 ÷ 所有参与增长的子项的
flex-grow总和 - 每个子项实际增长量 =
flex-grow× 可分配增量
注意:flex-grow: 0 的项不参与分配,哪怕它有 flex-basis;如果所有项 flex-grow 都是 0,则剩余空间留白。
示例:父宽 600px,三项 flex-basis: 100px,flex-grow 分别为 1、2、3 → 剩余空间 = 600 − 300 = 300px,总 flex-grow = 6 → 每份 50px → 三项最终宽度为 150px、200px、250px。
立即学习“前端免费学习笔记(深入)”;
flex-shrink 怎么算溢出空间?
它只在子项总 flex-basis 超过父容器主轴尺寸时触发,且收缩量不是线性减法 —— 它按「flex-shrink × flex-basis」加权,而非仅看 flex-shrink 值。
- 溢出空间 = 所有子项
flex-basis之和 − 父容器主轴尺寸 - 加权总和 = Σ(
flex-shrink×flex-basis) - 每项收缩量 = (溢出空间 ×
flex-shrink × flex-basis) ÷ 加权总和
这意味着:即使 flex-shrink 相同,flex-basis 越大的项收缩越多;反之,小项可能几乎不动。这也是为什么 flex: 1 在溢出时行为不可控 —— 它等价于 flex: 1 1 0,flex-basis: 0 导致加权总和极小,容易让某一项被过度压缩。
示例:父宽 400px,三项 flex-basis 为 200px、150px、100px,flex-shrink 全为 1 → 溢出 = 450 − 400 = 50px,加权总和 = 200 + 150 + 100 = 450 → 收缩量分别为 (200/450)×50 ≈ 22.2px、16.7px、11.1px。
flex-basis 是什么?为什么它不能被忽略?
flex-basis 是 flex 项在分配剩余/溢出空间前的“基准尺寸”,它优先级高于 width(当两者共存时,flex-basis 生效),默认值是 auto(取内容宽度或 width)。但它不是固定值 —— 浏览器会先用它算出初始布局,再按 flex-grow/flex-shrink 调整。
- 设
flex-basis: 0会让所有项从零开始增长,此时width被忽略,适合均分容器(如flex: 1) - 设
flex-basis: auto或具体值(如200px),则收缩时加权计算更“真实”,但容易因初始尺寸差异导致不均衡 - 常见坑:
flex: 1等价于flex: 1 1 0,而flex: auto等价于flex: 0 1 auto—— 行为完全不同
真正难调试的 flex 布局问题,90% 出在没显式声明 flex-basis,又误以为 flex-grow 是“百分比”或 flex-shrink 是“固定收缩量”。
最易被忽略的一点:flex-shrink 的加权计算中,flex-basis 是原始值,不是当前渲染宽度;所以 padding、border、box-sizing 都会影响它 —— 如果用了 box-sizing: border-box 但 flex-basis 设的是内容宽,结果就会偏差。


















