white-space属性控制空白符渲染方式,pre-wrap保留空格换行并折行,pre保留但不折行,pre-line合并空格仅保留换行;不能用normal恢复已折叠空格,需用 或pre类属性;动态插入须用innerHTML而非textContent。

white-space 属性决定空格是否被折叠
浏览器默认把 、\t、\n 全部合并成一个空格,这不是 bug,是 HTML 解析器的强制行为。想绕过它,唯一标准方式就是用 CSS 的 white-space 属性——它直接告诉渲染引擎“怎么处理这些空白符”。
最常用的是这三个值:
-
white-space: pre-wrap:保留所有空格和换行,且允许自动折行。适合用户输入、日志、诗歌等需格式又需响应式的场景 -
white-space: pre:保留所有空白,但不折行。超长内容会横向溢出容器,慎用于非代码块 -
white-space: pre-line:合并连续空格,只保留换行。效果接近普通段落,只是手动回车能生效
别在 <body> 或全局 class 上设 pre-wrap——按钮文字、导航链接里的空格也会被保留,可能意外撑开布局。
为什么不能用 style="white-space: normal" 强制恢复默认
normal 是默认值,显式声明等于没写。更关键的是:它只控制“如何解析空白”,不改变 HTML 解析阶段已发生的折叠。也就是说,如果你在源码里写了 hello world,解析器早把那四个空格压成一个了,white-space: normal 只是确认“就按这一个空格来渲染”,无法起死回生。
立即学习“前端免费学习笔记(深入)”;
真正要保留原始空格数量,必须让空白符在解析阶段不被触碰——要么用 硬塞(绕过解析),要么用 pre-类属性让解析器跳过折叠逻辑。
white-space 对内联元素的副作用容易被忽略
一旦给某个 <span> 或 <a> 设置了 white-space: pre-wrap,它内部的换行符(比如源码里的回车)也会被当真实换行处理,而不再是被忽略的空白。这可能导致:
- 文本在不该断行的地方折行(尤其配合
display: inline时) -
<span>内出现意外的块级行为,影响行高对齐 - 与相邻内联元素的 vertical-align 表现异常
验证方法:打开开发者工具,看 computed 样式中 white-space 是否生效,再检查元素盒模型里 line boxes 是否被拆成多行。
动态插入内容时 white-space 不生效的常见原因
用 JavaScript 往元素里写文本,比如 el.textContent = " hello ",即使该元素有 white-space: pre-wrap,页面上依然只显示一个空格。因为 textContent 不解析 HTML,所有空格照旧被 JS 字符串规则处理(JS 字符串本身不折叠,但后续插入 DOM 时仍走 HTML 解析流程)。
正确做法是:
- 改用
el.innerHTML = " hello "—— 此时空格进入 HTML 解析环节,white-space才起作用 - 或提前转义:用
el.innerHTML = " hello " - 服务端渲染或模板引擎中,确保空格未被模板自动 trim(如某些 JSX 默认 strip whitespace)
真正难调试的是混合场景:比如 Vue 的 {{ text }} 插值默认会保留空格,但若 text 来自后端 JSON,而 JSON 解析器又没动它,那空格就还在;可一旦中间经过 .trim() 或正则替换,就全没了。



















