纯css行号只显示一个“1”是因为浏览器不将code内换行符视为独立行块,::before仅触发一次;必须设code为display:block并确保每行形成块级上下文。

纯CSS行号为什么总只显示一个“1”
直接对 pre 或 code 设置 counter-reset: line,再用 code::before { counter-increment: line },结果只有第一行有编号、其余全空——这是最常见失败现象。根本原因是:浏览器不会把 code 内部的换行符当成独立“行块”,::before 伪元素只触发一次,不是每行一次。
必须让每一行成为可被 CSS 计数器识别的块级上下文。关键动作是:code 要设为 display: block,且内部每行需由换行符 + white-space: pre 共同作用生成视觉分行,但仅靠这个还不够可靠。
-
code必须设display: block,否则伪元素无法按行注入 - 不能依赖
pre自带的换行计数,它不支持counter-increment - 若代码含
<br>或动态插入内容,CSS 计数器会完全失效 - 缩进用 Tab 时,不同字体下宽度不一致,行号与代码列可能错位
Prism.js 行号插件怎么启用才不白配
Prism.js 的 prism-line-numbers 插件不是开箱即用。你引入了 JS 和 CSS,也加了 class="line-numbers",但页面没出现行号——大概率是漏掉了核心步骤:行号依赖预解析换行符并手动插入 <span></span> 包裹每行,所以必须确保代码内容在 DOM 加载完成前已存在(不能靠 JS 后续 innerHTML 注入)。
- HTML 中必须写成:
<pre class="line-numbers"><code class="js">...</code></pre>,line-numbers类必须挂在pre上,不是code - 代码内容里的
、<code>>、&仍需提前转义,否则 Prism 解析器会卡在非法 HTML 结构上 - 懒加载场景(如 tab 切换后才显示代码块),要手动调用
Prism.highlightAll(),否则行号不渲染 - 和
prism-live或自定义高亮逻辑共存时,行号可能重复插入,需检查是否多次初始化
Highlight.js 行号支持现状与替代方案
Highlight.js 官方从 v11 开始**已移除内置行号功能**。社区插件 highlightjs-line-numbers.js 虽可补上,但它依赖 hljs.highlightElement() 返回的 DOM 结构,而现代用法多为 highlightAll() 批量处理——这时插件常因节点未就绪而跳过。
更稳的做法是放弃行号插件,改用 Prism.js;或接受无行号,用语义化替代:在代码上方加一行说明,比如 <p><strong>src/utils.js</strong> 第 12–15 行:</p>。
- 别在 Highlight.js 初始化后强行 patch
code的 innerHTML 插入行号——破坏高亮 token 结构,语法颜色会乱 - 若坚持用 Highlight.js,可用
hljs.highlightElement(el)逐个处理,并在回调里用el.innerHTML.split('\n').map(...)手动包裹,但性能差、维护成本高 - 行号本质是 UI 辅助,非语义必需;屏幕阅读器不读行号,SEO 也不索引它,优先保证代码可访问性(如正确
lang属性)比强加行号更重要
手动注入行号的最小可行脚本
当 Prism.js / Highlight.js 都不可用,又必须有行号时,可写一段极简 JS,在 pre 渲染后立即处理。它不依赖任何库,只操作 DOM,兼容静态页面和简单 SPA。
document.querySelectorAll('pre[data-line-numbers]').forEach(pre => {
const code = pre.querySelector('code');
if (!code) return;
const lines = code.textContent.split('\n');
const numbered = lines.map((line, i) =>
`<span class="line" data-line="${i + 1}">${line}</span>`
).join('\n');
code.innerHTML = numbered;
pre.classList.add('has-line-numbers');
});
配套 CSS 只需两行:
pre.has-line-numbers code { display: block; }
pre.has-line-numbers .line::before { content: attr(data-line); display: inline-block; width: 3em; text-align: right; color: #999; margin-right: 1em; }
- 必须用
textContent读取原始字符串,避免 HTML 解析干扰 - 行号用
attr(data-line)而非 CSS 计数器,规避换行符解析歧义 - 若代码含
<script></script>标签或内联事件,此脚本会把它当普通文本处理,不执行——这是安全的 - 该方案不支持折叠/展开、当前行高亮等高级交互,仅解决“有无”问题
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











