先记住这个答案
flex-grow 分配的是容器主轴上的剩余空间。计算过程分两步:先算出剩余空间(容器宽度减去所有子项 flex-basis 之和),然后把这个剩余空间按照各子项 flex-grow 值的比例分配。每个子项的最终宽度等于它的 flex-basis 加上分到的那部分剩余空间。
- 分配的是剩余空间不是总空间
- 比例按
flex-grow值算 - 子项最终宽度 = basis + 分到的空间
- 所有 grow 为 0 时空间不分配
用数字走一遍分配过程
假设容器宽 600px,三个子项的 flex-basis 都是 100px,flex-grow 分别是 1、2、1。
剩余空间 = 600 - (100 + 100 + 100) = 300px。
flex-grow 总和 = 1 + 2 + 1 = 4。
子项 A 分到:300 x 1/4 = 75px,最终宽度 = 100 + 75 = 175px。子项 B 分到:300 x 2/4 = 150px,最终宽度 = 100 + 150 = 250px。子项 C 和 A 一样,175px。
.container {
display: flex;
width: 600px;
}
.item-a { flex: 1 0 100px; } /* 最终 175px */
.item-b { flex: 2 0 100px; } /* 最终 250px */
.item-c { flex: 1 0 100px; } /* 最终 175px */
/* 剩余空间 300px,按 1:2:1 分配 */注意 flex-grow: 2 不是说子项 B 的宽度是 A 的两倍。B 分到的额外空间是 A 的两倍,但最终宽度还要加上各自的 flex-basis。
flex-basis 不同时的陷阱
如果各子项的 flex-basis 不同,即使 flex-grow 相同,最终宽度也不一样。因为 flex-grow 只管剩余空间的分配,不管基础尺寸。
比如子项 A 的 flex-basis: 200px,子项 B 的 flex-basis: 100px,两个都是 flex-grow: 1。容器 600px,剩余空间 300px,各分 150px。A 最终 350px,B 最终 250px。虽然 grow 一样,但 A 比 B 宽。
想让两个子项不论内容多少都平分空间,要用 flex: 1(即 flex: 1 1 0%),让 flex-basis 为 0。这样所有空间都变成剩余空间,按 flex-grow 平分。
容易答错的地方
- 以为
flex-grow: 2就是占总空间的 2 份 flex-grow分配的是剩余空间,不是总空间。如果flex-basis不是 0,flex-grow: 2的子项最终宽度不一定是flex-grow: 1的两倍。- 以为
flex-grow: 1就是平分容器 - 只有在所有子项
flex-grow都是 1 且flex-basis都是 0(或相同)时,才是平分。如果flex-basis不同,最终宽度也不同。
面试官还会怎么问?
没有剩余空间时 flex-grow 有什么效果?
没有效果。如果子项的 flex-basis 总和已经等于或超过容器宽度,剩余空间为 0 或负数,flex-grow 不会增加任何宽度。超出的部分由 flex-shrink 处理。
flex-grow 的值可以是小数吗?
可以。flex-grow: 0.5 表示分到剩余空间的比例更小。比如两个子项分别是 0.5 和 1.5,总和 2,分别分到 25% 和 75% 的剩余空间。
flex-grow 会让子项超过 max-width 吗?
不会。max-width 是硬限制。如果 flex-grow 算出的宽度超过 max-width,子项停在 max-width,多出来的空间会重新分配给其他子项。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。