counter 是给代码块加行号最可控的方式,因其无需预处理、不依赖 js、兼容主流浏览器,且通过 css 计数器+::before 精确控制样式位置;必须用 div 包裹每行并配合 counter-reset/increment/counter(content) 实现,同时注意留白、对齐、复制屏蔽及行高一致。

为什么 counter 是给代码块加行号最可控的方式
因为不需要预处理、不依赖 JS、兼容性好(Chrome/Firefox/Safari/Edge 均支持),且能精确控制样式位置。用 pre 或 code 元素本身无法直接生成行号,必须借助 CSS 计数器 + ::before 伪元素;否则容易出现行号错位、换行丢失或复制时带出行号等问题。
基础结构:确保 HTML 有可计数的行级容器
不能直接对 pre 使用 counter-increment —— 它没有子行概念。必须把每行代码包裹在 div 或 span 中(推荐 div,语义清晰、换行自然):
<pre class="code-block">
<div>console.log('hello');</div>
<div>const a = 1 + 2;</div>
<div>return a * 10;</div>
然后通过 CSS 为每个 div 触发计数器递增:
-
counter-reset必须放在父容器(如.code-block)上,初始化计数器 -
counter-increment放在子div上,每次渲染一行就 +1 -
::before插入内容时,用counter(content)读取当前值
关键样式:对齐、宽度与空白处理
行号默认左贴边、文字右对齐,但容易和代码内容重叠。常见错误是忘记设置 display: table-cell 或 position: absolute 导致布局错乱:
- 给
.code-block设置counter-reset: line; - 给
.code-block > div设置:counter-increment: line;和position: relative; - 给
.code-block > div::before设置:content: counter(line);、position: absolute;、left: -3em;、width: 2.5em;、text-align: right;、color: #999; - 必须给
.code-block加padding-left: 3.5em;,为行号区域留白,否则代码会覆盖行号
若使用 display: table 方案,需额外设 table-layout: fixed 防止列宽被长代码撑开。
容易被忽略的细节:空行、缩进与复制行为
空 div 仍会触发 counter-increment,导致行号连续但视觉“跳行”;缩进用 tab 还是空格不影响计数,但会影响 white-space 渲染;复制代码时默认会复制 ::before 内容 —— 如果不希望行号被复制,加 -webkit-user-select: none; 和 user-select: none; 到 ::before 上。
多语言混排或超长行可能造成行号垂直偏移,此时要检查 line-height 是否在 div 和 ::before 中一致,否则数字会浮高或下沉。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











