← 🧲 Flexbox · 简写语义与对齐边界 / flex-wrap: balance:让换行分布更均衡 待审核 14 / 14
flex-wrap: balance · 提案

flex-wrap: balance:让换行分布更均衡

flex-wrap: wrap 的换行是贪心(greedy)的:从左到右尽量填满当前行,放不下才换行。后果是最后一行常常只剩一两项,各行长度参差——标签云、商品卡、相册尤其明显。flex-wrap: balance 是正在推进的新值(csswg-drafts #3070),思路类比 text-wrap: balance:用 Knuth–Plass 式的算法让各行长度尽量接近

1 · 贪心 vs 均衡:同一批 item,两种分行

左右两列同样的 item、同样的容器宽,只是分行策略不同。每行末尾标了该行的实测总宽:贪心列各行宽度参差(末行常常很空),均衡列各行宽度挤在一个窄区间。拖滑块改 item 数,看末行的变化。读数区列出两种策略的行宽极差与区间。

这里的「均衡」是怎么算的? 现状下浏览器还没有原生 flex-wrap: balance(见下方横幅与支持说明),所以这一列是本页 JS 模拟:先用贪心求出最少行数 L,再用动态规划在所有「切成 L 段」的方案里,选取各行剩余空间 (slack) 平方和最小的那个。行数固定时各行 slack 之和恒定,对 slack 计平方惩罚会促使各行 slack 趋同——于是行宽趋匀、末行也被填满,不再留下单独的孤项。这是 Knuth–Plass 断行的简化版,「各行趋于等长」的直观效果一致

2 · 它和 justify-content 是两件事

二者容易混淆:justify-content 管的是每一行内部如何对齐 / 分配剩余空间(见 居中即截断safe / unsafe);flex-wrap: balance 管的是item 在哪里断到下一行——即如何切行。一个作用于行内,一个作用于行间。balance 落地后两者可以叠加:先由 balance 决定每行放几个,再由 justify-content 排布该行。

3 · 现状与近似手段

截至 2026,各引擎都尚未默认实现 flex-wrap: balance(本页顶部横幅是实测 CSS.supports('flex-wrap','balance'))。它仍处于提案阶段,但已被多次讨论,也有 Chromium 的探索性实现。目前要实现「均衡换行」只能近似:用 JS 计算分行(如本页),或在已知行数时用 flex-grow 让每行项目拉伸填满。一旦原生支持,这些近似手段都能被一行 flex-wrap: balance 取代(见上方 lab 底部的对照代码)。

4 · 🔗 真实效果参考

  • flex-wrap: balance 实例 demo · CodePen / yisi — 一个可直接拖拽体验的 flex-wrap: balance 演示(在支持的引擎 / 开了实验标志时是原生效果)。对照本页的 JS 模拟看「各行趋于等长」的直观差异。
  • bfgeek / flex-wrap-balance explainer · github.com — Ian Kilpatrick(Chromium 布局团队)的提案说明:为什么需要它、Knuth–Plass 式断行如何套到 flex item 的 hypothetical main-size 上。