highlight.js 仅支持 <pre><code> 嵌套结构高亮,单行 <code> 不被处理;需转义 HTML 字符、规范 language class,并在 highlightElement() 后用 DOM 或行偏移定位目标行。

highlight.js 不支持直接高亮单行 标签</H3>
<p>你写的是 <code><code>console.log(1)</code></p>,哪怕加了 <code>class="js"
,highlight.js 也完全不处理——它只扫描 <pre><code> 嵌套结构。单行 标签没有换行信息、没有缩进上下文,语法解析器根本没法判断哪是关键字、哪是字符串。强行塞进去,结果就是纯等宽字体,没颜色、没 token 分类。</p>
<H3>想高亮“某一行”,得先把它放进 <pre class="brush:php;toolbar:false;"><code> 里</H3>
<p>所谓“高亮某一行”,本质是给那一行的 DOM 节点加 class(比如 <code>hljs-line-active
),但前提是整块代码已由高亮库解析完毕,且被包裹在 <pre><code> 中。否则连基础 token 化都不存在,更别说定位行了。
- 必须用
<pre><code class="js">...</code></pre> 结构,不能省略 <pre>
- HTML 特殊字符要提前转义:
< → ,<code>> → >,& → &,否则浏览器会误解析成真实标签
- 语言 class 必须规范:用
language-js 或 lang-js,别写 javascript 或 js(highlight.js 严格匹配前缀)
手动标记某一行:用 data-line + CSS 或 JS
<pre><code class="js">...</code></pre> 结构,不能省略 <pre>
< → ,<code>> → >,& → &,否则浏览器会误解析成真实标签
language-js 或 lang-js,别写 javascript 或 js(highlight.js 严格匹配前缀)data-line + CSS 或 JS高亮库本身不提供“高亮第 3 行”这种 API,但你可以借助解析后生成的 HTML 结构做后处理。常见做法是:
- 在
<code>上加自定义属性,比如<code class="js" data-highlight-line="3"> - 等
highlight.js执行完(hljs.highlightAll()后),用 JS 查找第 3 个<span class="hljs-...">所在的文本行(注意:不是<span>的层级,而是按换行符切分后的逻辑行) - 给该行外层容器(通常是
<span>或<div>,取决于主题)加背景色或边框,例如:background-color: #fff9c4; - 更稳的做法是配合
<pre>的line-height和font-size,用伪元素 +nth-of-type定位,但需确保高亮后 DOM 是每行一个块级节点(部分主题如github-dark不满足)
真正动态的行高亮:适合 Markdown 渲染后场景
如果你的代码块是 JS 动态插入(比如用 marked 渲染 Markdown),那必须在插入后手动触发两件事:
立即学习“前端免费学习笔记(深入)”;
- 调
hljs.highlightElement(codeEl)(比highlightAll()更精准,避免重复处理) - 再执行你的行标记逻辑,比如:
const lines = codeEl.textContent.split('\n'); lines[2] && codeEl.children[2]?.classList.add('highlighted');(注意:要等高亮完成后再查children,因为原始文本已被替换成带 class 的<span>) - 别依赖
innerHTML去正则匹配行号——高亮后 HTML 结构复杂,<span>嵌套深,正则极易错位
最易忽略的一点:行号是从 1 开始数,但数组索引从 0 开始;DOM 节点顺序和原始换行顺序未必严格一致(尤其含注释或模板字符串时)。真要可靠,得结合 hljs.highlightElement() 返回的 value 字段做行偏移计算,而不是硬写 [2]。



















