的空白保留发生在 html 解析阶段而非 css 控制;浏览器遇 标签即启用预格式化解析路径,保留所有空格、tab、换行为独立文本节点,即使无 css 也生效;white-space: pre 仅是对非 元素的渲染 fallback。

pre 标签的空白保留发生在 HTML 解析阶段,不是 CSS 控制的
pre 的“保留空格换行”不是靠 white-space: pre 这类样式实现的,而是浏览器在解析 HTML 时,一旦遇到 <pre class="brush:php;toolbar:false;"></pre> 开始标签,就切换到「预格式化文本」解析路径:所有空格、Tab(U+0009)、换行(U+000A / U+000D)都被当作独立的 Text 节点保留在 DOM 中,不经过默认的空白压缩逻辑。这意味着——
- 即使你没写任何 CSS,
<pre class="brush:php;toolbar:false;"> a\n\nb\tc</pre>在 DOM 里就是 4 个空格 + 文本 + 换行 + 换行 + 文本 + Tab + 文本 - 如果用
innerHTML = ' x\ny'动态赋值,\n 会被 JS 字符串解析为换行符,但若源字符串来自模板转义或拼接截断(比如被 URL 编码或 \r\n 被误处理),DOM 中就根本不会出现换行节点 -
white-space: pre是渲染阶段的 fallback 行为,仅对非<pre class="brush:php;toolbar:false;"></pre>元素生效;对<pre class="brush:php;toolbar:false;"></pre>自身,它只是浏览器默认样式的组成部分,删掉也不会让空白“消失”,但可能影响换行策略(如是否折行)
等宽字体不是可选项,是排版对齐的前提
pre 保留了空格和 Tab 的字符数量,但它们能否对齐,完全取决于字体。非等宽字体(如 Arial、system-ui)会让空格、字母、中文宽度不一致,导致缩进塌陷、ASCII 表列错位。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 必须显式设置
font-family: ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace,优先包含系统级等宽字体 - 避免只写
monospace—— 某些旧 Android 或 Linux 系统 fallback 到不支持中文的等宽字体,造成中文字体降级失真 - 如果
<pre class="brush:php;toolbar:false;"></pre>内嵌了<code>,记得给<code>单独设等宽字体,否则继承链可能被父级 CSS 中断 - Tab 宽度不可靠,建议统一用空格缩进(如 2 或 4 个),并配
tab-size: 4控制显示宽度
动态注入内容时,textContent 才是安全选择
用 innerHTML 往 <pre class="brush:php;toolbar:false;"></pre> 里塞字符串,哪怕内容本身含 \n,也极容易出问题:尖括号被当标签解析、& 被二次转义、换行符在某些构建工具中被自动 trim。
- 始终优先用
el.textContent = sourceString,它绕过 HTML 解析器,把字符串原封不动转成纯文本节点 - Vue 中不要用
{{ }}插值(默认转义),改用v-text或v-html(后者需确保内容可信) - React 中用
{sourceString}是安全的(JSX 默认 textContent 行为),但若来源是用户输入,仍需提前 HTML 转义(如用DOMPurify.sanitize()) - 服务端模板(EJS/Jinja)要确认是否启用了默认转义,未转义输出需显式调用
或{{ raw|safe }}
pre 不是万能容器,嵌套 HTML 标签会破坏格式语义
<pre class="brush:php;toolbar:false;"></pre> 允许子元素存在,但它的“预格式化”只作用于纯文本节点。一旦插入块级标签(如 <p></p>、<div>),这些元素会脱离 pre 的空白上下文,按自身规则布局,导致换行、margin、缩进全部失效。
<ul>
<li>可以安全嵌套 <code><code>、<strong></strong>、<span></span> 等内联元素,它们不影响行内空白流
<span class="keyword">function</span>,改用 Prism.js 或 highlight.js,它们在 token 化后仍保持原始空白结构<div>hello</div>,或用 <code> 包裹再配合语法高亮库
<pre class="brush:php;toolbar:false;"></pre> 的保护只在初始 HTML 解析时生效;后续任何 JS 修改、框架重渲染、CSS white-space 覆盖,都会让格式“掉盾”










