pre里直接写<或&会触发HTML解析,因pre仅保留空白符和换行,不阻止标签解析;未转义时浏览器将尝试解析为HTML元素,导致格式崩坏、样式失效等问题。

pre里直接写或会触发HTML解析</H3>
<p><code>pre
本身不阻止浏览器解析标签,它只保留空白符和换行。只要里面出现未转义的 或 <code>&,浏览器就会当成真实HTML处理——哪怕你本意只是展示一段带尖括号的代码。
常见错误现象包括:
- 原始代码里的
<div> 被吃掉,后续内容错位
<li>
<code>pre 块提前闭合,后面 DOM 结构全乱
- 手动插入的
<span class="keyword">if</span> 被当成未闭合标签,触发浏览器自动补全,破坏高亮结构
根本原因不是 pre 有问题,而是你传给它的字符串里混入了未经转义的 HTML 字符。它忠实地渲染你给的内容,不管那是不是“你想显示的代码”。
必须用 <pre class="brush:php;toolbar:false;"> 嵌套,不能只用 <pre class="brush:php;toolbar:false;"> 或只用 <code></H3>
<p>单独用 <code>pre
:能保留缩进和换行,但语义缺失,屏幕阅读器无法识别这是代码块,CSS 也难精准选中;
立即学习“前端免费学习笔记(深入)”;
单独用 code:它是行内元素,\n 和多余空格全被忽略,结果就是所有代码挤成一行。
正确结构只有这一种:
function a() {\n return 1;\n}。其中:
-
pre 负责保留格式(换行、空格、\t)
-
code 负责声明语义(“这是计算机代码”,影响可访问性、SEO、CSS 选择器)
-
class="js" 是可选但强烈推荐,用于后续语法高亮或 JS 处理
动态插入时别用 innerHTML +=
对已有 pre 做增量操作(比如加高亮),直接改 innerHTML 极易出问题:
- 清空当前光标位置和用户 selection
- 已有的
span 节点可能被重新解析,导致样式丢失或嵌套错乱
- 若拼接字符串时漏转义,
又会被当标签解析
更安全的做法是:
- 先用
element.textContent 拿纯文本,避免误读已有标签
- 基于纯文本坐标算出高亮起止位置
- 用
Range + DocumentFragment 精准包裹目标文本节点,不碰 innerHTML
转义是硬性前提,CSS 或 JS 都救不了
HTML 解析阶段就发生的破坏,没有回旋余地。以下字符必须在插入前转义:
→ <code><
-
> → >
-
& → &
别指望 white-space: pre 或 Prism.js 自动帮你转——它们运行在 DOM 已构建之后,而解析错误早在那之前就毁了结构。动态生成时,务必先构建完整转义后的字符串,再一次性赋值给 innerHTML,而不是边拼边插。
最容易被忽略的一点:即使你用了 pre + code,只要漏转一个 &,整个代码块就可能从中间断裂,且这种错误在开发者工具里看不出明显报错,只能靠肉眼比对渲染结果和原始字符串。
<div> 被吃掉,后续内容错位
<li>
<code>pre 块提前闭合,后面 DOM 结构全乱<span class="keyword">if</span> 被当成未闭合标签,触发浏览器自动补全,破坏高亮结构根本原因不是 pre 有问题,而是你传给它的字符串里混入了未经转义的 HTML 字符。它忠实地渲染你给的内容,不管那是不是“你想显示的代码”。
必须用 <pre class="brush:php;toolbar:false;"> 嵌套,不能只用 <pre class="brush:php;toolbar:false;"> 或只用 <code></H3>
<p>单独用 <code>pre
:能保留缩进和换行,但语义缺失,屏幕阅读器无法识别这是代码块,CSS 也难精准选中;
立即学习“前端免费学习笔记(深入)”;
单独用 code:它是行内元素,\n 和多余空格全被忽略,结果就是所有代码挤成一行。
正确结构只有这一种:
pre 负责保留格式(换行、空格、\t)code 负责声明语义(“这是计算机代码”,影响可访问性、SEO、CSS 选择器)class="js" 是可选但强烈推荐,用于后续语法高亮或 JS 处理innerHTML +=
pre 做增量操作(比如加高亮),直接改 innerHTML 极易出问题:span 节点可能被重新解析,导致样式丢失或嵌套错乱 又会被当标签解析
element.textContent 拿纯文本,避免误读已有标签Range + DocumentFragment 精准包裹目标文本节点,不碰 innerHTML
→ <code><> → >
& → &
white-space: pre 或 Prism.js 自动帮你转——它们运行在 DOM 已构建之后,而解析错误早在那之前就毁了结构。动态生成时,务必先构建完整转义后的字符串,再一次性赋值给 innerHTML,而不是边拼边插。pre + code,只要漏转一个 &,整个代码块就可能从中间断裂,且这种错误在开发者工具里看不出明显报错,只能靠肉眼比对渲染结果和原始字符串。



















