先记住这个答案
flex-basis 的百分比值相对于 flex 容器在主轴方向上的内部尺寸(content-box 的宽度或高度)来计算。比如容器宽 600px,子项 flex-basis: 50% 就是 300px。如果容器没有设明确的主轴尺寸,百分比无法计算,浏览器会回退为 content,按内容大小来算。
- 百分比相对容器主轴尺寸算
- 容器无尺寸时回退为内容大小
0和0%行为不同- 百分比不含容器的
padding
百分比的计算基准
flex-direction: row 时,flex-basis 的百分比相对容器的宽度(content-box)。flex-direction: column 时,相对容器的高度。注意是 content-box 的尺寸,不是 border-box。如果容器有 padding,百分比的基准是减去 padding 后的尺寸。
flex-basis 的计算CSS.container {
display: flex;
width: 600px;
padding: 0 20px; /* content-box 宽度 = 560px */
box-sizing: border-box;
}
.item {
flex-basis: 50%; /* 50% × 560px = 280px */
}如果容器是 box-sizing: content-box(默认),width: 600px 就是 content-box 宽度,百分比直接按 600px 算。
容器没有尺寸时百分比会回退
如果容器没有设 width(或 column 下没设 height),容器的尺寸由内容决定,是一个不确定的值。这时百分比 flex-basis 无法计算,浏览器按规范回退为 content,用子项内容的固有尺寸作为基础尺寸。
这个回退行为容易踩坑:你以为设了 flex-basis: 50% 子项会占一半,结果容器没有明确宽度,50% 毫无意义,子项按内容大小排列。
0 和 0% 的微妙区别
flex-basis: 0 是一个固定的零长度,子项的基础尺寸就是 0,所有容器空间都变成「剩余空间」由 flex-grow 分配。
flex-basis: 0% 虽然也是零,但它走的是百分比解析流程。在容器有明确尺寸时,0% 计算结果也是 0,和 0 一样。但在容器没有明确尺寸时,0% 可能回退为 content,表现就和 0 不同了。
实际项目中一般用 0(flex: 1 展开就是 flex: 1 1 0%),很少刻意区分。但面试时可能会问到这个区别。
容易答错的地方
- 以为百分比相对 border-box 计算
- 百分比的基准是 content-box 尺寸,不是 border-box。如果容器有
padding,50%不是容器总宽度的一半,而是减去padding后的一半。 - 以为百分比在容器没有宽度时仍然生效
- 容器宽度不确定时,百分比
flex-basis回退为内容尺寸。这是经常被忽略的行为。
面试官还会怎么问?
flex-basis: 50% 加 flex-grow: 1 后子项会变多宽?
基础尺寸是容器的 50%,然后剩余空间(另外 50%,减去其他子项的 flex-basis)按 flex-grow 比例分配。最终宽度等于 50% 加上分到的剩余空间。
两个子项都设了 flex-basis: 50%,为什么加起来会超过 100%?
如果两个子项之间有 gap,或者子项有 margin、padding、border,这些都会占用空间。flex-basis: 50% 只是基础尺寸,加上这些额外空间就超过 100%,子项会被 flex-shrink 压缩。
width: 50% 和 flex-basis: 50% 哪个优先?
flex-basis 优先(除非 flex-basis 是 auto)。如果同时设了 flex-basis: 50% 和 width: 30%,基础尺寸按 flex-basis 的 50% 来算。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。