CSS计数器自动编号需三步:先在父容器用counter-reset初始化计数器,再对每个p用counter-increment递增,最后通过p::before的content: counter(name)显示序号;漏掉reset或命名不一致会导致编号异常。
counter-increment 给 <p> 自动编号直接给每段文字加序号,核心是用 CSS 计数器配合 ::before 伪元素。不需要 JS,也不用手动写 1.、2.,浏览器会自动维护序号。
关键在于两步:先声明并递增计数器,再在伪元素里显示它。常见错误是只写了 counter-increment 却忘了 counter-reset 初始化,或者把 content 写成纯文本没调用 counter() 函数。
counter-reset: section; 放在父容器(比如 <article> 或 <body>)上,表示从 0 开始新建一个叫 section 的计数器p { counter-increment: section; } 让每个 <p> 触发一次 +1p::before { content: counter(section) ". "; } 把当前值插入到段落开头编号异常通常源于计数器作用域或初始化时机问题。最典型的是把 counter-reset 写在 p 上——这会导致每个段落都重置计数器,结果全是 1;或者完全漏掉 counter-reset,此时 counter(section) 返回空值,content 渲染为 "" 或触发降级行为(部分浏览器显示 NaN)。
counter-reset 在所有目标 <p> 的**共同祖先元素**上声明,且只声明一次counter-reset: chap1; 和 counter-reset: chap2;
counter() 的老浏览器(IE8 及以下)会忽略 content,需考虑降级方案(如服务端注入)counter() 与 counters() 的区别和使用场景counter(section) 返回单级计数器的当前值,适合平铺编号;counters(section, ".") 用于嵌套结构(如多级标题),会拼接所有同名计数器的层级值,例如 1.2.3。对纯段落列表,基本用不到 counters()。
立即学习“前端免费学习笔记(深入)”;
counter(section) 段”),直接拼在 content 字符串里:content: "第" counter(section) "段:";
counter-reset: section 5; 表示从 6 开始编号(因为 increment 是在 reset 后+1)counter-increment: none;,或用类选择器避开:p.no-num { counter-increment: none; }
CSS 计数器本身开销极小,但若在超长文档(几千个 <p>)中滥用嵌套或频繁重置,可能影响渲染效率。更大的隐患是语义缺失——屏幕阅读器通常不会读出 ::before 生成的内容,编号对无障碍用户不可见。
<ol><li>)或 ARIA 属性补充content 中放重要信息,因为它无法被复制、搜索或翻译<p>,要确保它处于已声明 counter-reset 的上下文中counter-reset 必须存在——哪怕只是写在 body 上。