标签本身不支持行号,因其是语义化内联元素,仅用于标记短代码片段;带行号的代码块需用组合配合css计数器或prism.js等工具实现,且须兼顾可访问性与复制体验。

为什么 标签本身不支持行号
<code> 是语义化内联元素,设计用途是标记一小段程序代码(比如函数名或变量),浏览器不会解析换行、也不提供行号渲染能力。你看到的“带行号的代码块”,实际是 <code><pre class="brush:php;toolbar:false;"></pre> + <code> 组合,再靠 CSS 或 JS 注入行号——直接往 <code> 里加行号,要么无效,要么破坏语义和可访问性。
用 <pre class="brush:php;toolbar:false;"><code></code> 配合 CSS 实现静态行号(无 JS)</pre>
这是最轻量、兼容性最好、也最可控的方式。核心思路:用 counter-reset 和 ::before 伪元素为每行生成序号。
关键点:
-
<pre class="brush:php;toolbar:false;"></pre>必须保留换行和空格(white-space: pre是默认行为,别覆盖它) <code>仅作为语义容器,不参与样式计算;行号由<pre class="brush:php;toolbar:false;"></pre>的子元素伪类控制- 每行必须用
<br>或真实换行符(\n)分隔,不能靠display: block强行折行
<pre class="brush:php;toolbar:false;"><code class="js">function hello() {
console.log('world');
return true;
}</code>
CSS 示例:
pre {
counter-reset: line;
padding-left: 40px;
}
pre code {
display: block;
}
pre code::before {
content: counter(line);
counter-increment: line;
display: inline-block;
width: 30px;
margin-left: -40px;
text-align: right;
color: #999;
}
用 Prism.js 或 Highlight.js 动态添加行号(推荐用于多语言)
如果你要高亮语法 + 行号 + 多语言支持,硬写 CSS 很难维护。Prism.js 的 line-numbers 插件是事实标准,但要注意加载顺序和初始化时机。
常见错误:
- 只引入
prism.js主文件,没引入prism-line-numbers.js插件 - HTML 中漏掉
class="line-numbers"到<pre class="brush:php;toolbar:false;"></pre>上(不是<code>) - 在 DOM 渲染前就调用
Prism.highlightAll(),导致部分代码块未处理
正确用法示例:
<link href="prism.css" rel="stylesheet"><link href="prism-line-numbers.css" rel="stylesheet"><script src="prism.js"></script><script src="prism-line-numbers.js"></script><pre class="line-numbers"><code class="py">def fib(n):
return n if n </code>
行号对可访问性和复制的影响必须手动修复
所有基于伪元素或绝对定位的行号方案,都会让行号文字无法被选中、无法被屏幕阅读器识别,且复制代码时会把行号一起拷进去(除非额外拦截)。
解决办法很实在:
- 给
::before加user-select: none防止误选行号 - 用
aria-hidden="true"告诉读屏软件忽略行号区域 - 如果用 Prism,启用
data-prismjs-copy="true"属性并配合prism-copy-to-clipboard插件,它会自动过滤行号文本
别指望“一次配置全搞定”——行号永远是视觉增强层,和内容分离是必须坚持的设计原则。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











