配了八年排版,今天才发现标题换行从来不需要靠 br 标签——CSS 把这件事彻底原生化了

写过营销页的工程师大概都见过这个画面——标题明明可以排成两行均匀的 “Build / accessible interfaces”,浏览器偏偏给它断成了 “Build accessible / interfaces”,第二行孤零零落了一个词在那儿。

这个问题在业内有个名字:标题孤儿(headline orphan)。以前靠手敲 <br> 标签,或者给设计师发消息问”这行够不够长”。今天这事儿被一行 CSS 彻底原生化了。

text-wrap: balance 是什么

一行 CSS 属性,让浏览器自动把标题的每行字符数分配均匀:

h1, h2 {
  text-wrap: balance;
}

全球覆盖率:92.72%(Chrome 114+、Firefox 121+、Safari 17.5+、Edge 114+,均已稳定)

以前怎么解

手敲 <br>:最常见,但脆弱——内容一变或翻译一次,断行位置就错了。

Balance-Text.js:一个 8KB 的 JavaScript 库,在 paint 之后测量文本宽度,重新 reflow 找最佳断点。有效,但有性能代价。

&nbsp; 强制不断开:治标不治本,一旦 viewport 变窄或翻译后文字长度变化,整行直接溢出容器。

三种方法都有一共同问题:断行是”死的”,内容一变就要重新维护。

现代解法:一行 CSS

text-wrap: balance 由 Chrome 团队在 2023 年提出,2024 年进入 Baseline 2024,现在 92% 全球覆盖率,完全可以投产。

原理:浏览器在布局阶段用二分查找找最优换行点,然后把换行限定在 6 行以内(Chromium 实现),所以算法复杂度是常数级别,不会影响性能。Lighthouse 审计显示一页 20 个 text-wrap: balance 的标题,布局耗时增加 < 1ms。

三个优势:

  • 零脚本:不需要加载任何 JS 库,也不需要初始化代码
  • 零 DOM 读取:在布局阶段完成,不触发重排或重绘
  • 浏览器原生优化:跨浏览器的 synthetic dataset 训练,匹配各国语言断词习惯

三个坑

1. 6 行上限:超过 6 行后浏览器静默关闭 balance(不报错,只是失效)。这对标题来说永远够用,但不要用在 body 文本上——长段落请用 text-wrap: pretty(专门优化段落末尾孤词)。

2. 不要在动画标题上用:如果一个标题的宽度在逐帧动画化(比如手风琴展开折叠面板),balance 每帧都要重新计算,可能让 60fps 掉到 50fps。这种场景用 text-wrap: pretty 或默认 wrap。

3. 不要和应用了 white-space: nowrap 的元素叠加:nowrap 禁用了所有换行,balance 无从优化。

三步下一步

第一步:找出你设计系统里所有手写了 <br> 或 nbsp 的标题,列个清单。

第二步:统一换成 text-wrap: balance,全局加一行。然后逐个验证断行效果——特别关注翻译后变长的标题。

第三步:检查有没有覆盖 white-space: nowrap 的场景,是的话单独写 text-wrap: wrap 恢复默认行为。

收尾

一行代码,全球 92% 设备直接生效。从今天起,标题不再有孤儿,行尾不再有悬空词。屏幕阅读器读到的是完整句子,搜索引擎看到的是原始文本,完全向后兼容。

旧项目里那些手敲的 <br> 和 nbsp,今晚回家前可以顺手删了。

评论区

0 条评论

登录后可评论。