配了多年 pre-wrap,今天才知道 white-space 其实拆成了两个独立属性

CSS 写久了,white-space: pre-wrap 这四个字你闭着眼睛都能写出来。但你知道吗,Chrome 94 就悄悄把 white-space 拆成了两个独立属性:white-space-collapse 控制空格怎么合并,text-wrap-mode 控制换行方式——只是 Safari 一直没接,一直没火。

Safari 18.2 终于把这两个属性补完了。

说人话:这两个属性到底干了什么

white-space-collapse 决定了空格字符的命运:

  • collapse:连续空格合并成一个,这是默认值,也就是你熟悉的 normal 行为
  • preserve:空格全部保留,换行也保留,就是 pre 的效果
  • preserve-breaks:空格合并,换行符保留,就是 pre-line 的效果
  • preserve-spaces:空格保留,但 tab 不转空格
  • break-spaces:和 preserve 类似,但行尾空格会占位且可打断

text-wrap-mode 就简单多了,只有 wrapnowrap 两个值,控制要不要换行。

为什么要拆出来

原来的问题是:你想单独控制「空格合并」但不控制「换行」,做不到。white-space 是打包好的四个固定组合:normal / pre / pre-wrap / pre-line,你想自定义?CSS 之前不支持。

拆成两个独立属性之后,你可以这样写:

/* 空格全保留,但允许换行 —— 以前只能 white-space: pre-wrap */
white-space-collapse: preserve;
text-wrap-mode: wrap;

/* 空格合并,但强制不换行 —— 以前只能 white-space: nowrap */
white-space-collapse: collapse;
text-wrap-mode: nowrap;

/* 空格保留,换行符保留,但行尾空格不占位 —— 以前根本没有等价写法 */
white-space-collapse: break-spaces;
text-wrap-mode: wrap;

最后一种 break-spaces 特别有用。pre-wrap 的问题是行尾空格会「挂」在行尾,不算进行宽,布局计算时会丢。break-spaces 把这个问题修了:行尾空格真正占位,盒子的 intrinsic size 计算是准确的。

break-spaces 的实际场景

代码编辑器、终端模拟器、邮件正文渲染——这类场景最怕行尾空格悄悄消失,导致对齐错乱:

.code-block {
  /* 空格真实占位,columns 计算准确 */
  white-space: break-spaces;
}

浏览器支持情况(2026 年 9 月)

white-space-collapsetext-wrap-mode 早在 2024 年就进了 Baseline Low,Chrome 94+ / Firefox 121+ / Safari 15.4+ 就支持了,Safari 18.2 才补完主要功能,完整的 5 种 collapse 值全部稳定。

white-space 简写可以无损兼容所有浏览器:

/* 渐进增强:先写简写兜底,再单独覆盖需要细粒度控制的维度 */
.code-block {
  white-space: pre-wrap; /* 老浏览器 / 兜底 */
  white-space-collapse: preserve;
  text-wrap-mode: wrap;
}

下一步你可以做的

如果你的项目里还在用 white-space: pre-wrap 处理代码展示、终端输出或格式化文本,先跑一遍看看有没有行尾空格导致的对齐问题;有的话,换成 break-spaces,盒子尺寸计算会准很多。如果你在封装一个通用的文本渲染组件,把 white-space-collapsetext-wrap-mode 单独暴露出来,让调用方可以按需组合——比原来的四种固定模式灵活得多。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 11 阅读