CSS计数器做自动编号。

CLARA轻量论坛系统
CLARA轻量论坛系统 星耀SVIP管理员 黑卡会员
发布于 2026-09-17 10:15 ·7 浏览 ·0 回复

CSS 计数器(CSS Counters)能用三行声明给任何重复元素自动编号:`counter-reset` 定起点、`counter-increment` 递增、`content: counter()` 显示,不写 JS、不手写数字,增删条目后编号自动重排。

三步走:reset、increment、显示

结论:CSS 计数器永远是同一个套路——父级归零、子项递增、伪元素显示,三者缺一不可。

.list { counter-reset: item; }             /* 1. 定义计数器并归零,作用域含所有后代 */
.list > li { counter-increment: item; }    /* 2. 每个子项 +1 */
.list > li::before {
  content: counter(item) ". ";             /* 3. 输出当前值 */
  color: #888;
}

三点必须记牢:

第一,`counter-reset` 写一次就够,写在父容器上,所有后代共享同一个计数器实例。写在每个 li 上会导致每个都是 1。想从 10 开始编号,写 `counter-reset: item 9`,元素递增后就是 10。

第二,`content` 只在 `::before`、`::after`、`::marker` 里生效。把 `content` 写在普通元素上不会有任何效果,这是新手最常见的踩坑点。

第三,`counter-increment` 建议写在元素本身而不是 `::before` 上,语义更清楚,也不受伪元素盒模型影响。

编号样式:罗马数字、中文、前导零都不用自己拼

结论:`counter()` 的第二个参数直接复用 `list-style-type` 那一套取值,想要什么格式改参数就行。

  • `content: counter(item, upper-roman)` → I. II. III.
  • `content: counter(item, lower-alpha)` → a. b. c.
  • `content: counter(item, cjk-decimal)` → 一、二、三
  • `content: counter(item, decimal-leading-zero)` → 01、02、03

如果这些还不够,用 `@counter-style` 自定义规则集,可以定义前后缀、进制、循环符号,注册后同样能传给 `counter()` 使用。

嵌套编号:1.1、1.2 用 counters()

结论:多级列表要用带 s 的 `counters()`,它会把同名计数器在各层的值拼接成一条链。

ol { counter-reset: sec; list-style: none; }
li { counter-increment: sec; }
li::before { content: counters(sec, ".") " "; }
ol ol { counter-reset: sec; }   /* 进入下一层时归零,实现 1.1 / 1.2 */

`counters(sec, ".")` 的第二个参数是连接符,换成 `"-"` 就得到 1-1、1-2 的效果。文章目录、多级大纲、章节编号都靠这个。

四个容易翻车的细节

结论:计数器好用,但有几个行为跟直觉不一样,提前知道能省一小时调试。

  1. `display: none` 的元素不参与计数,用它做「条件显示 + 连续编号」会断号。
  2. 计数器名区分大小写,`item` 和 `Item` 是两个互不相干的计数器。
  3. 伪元素里的编号不进剪贴板,也不会被屏幕阅读器朗读。如果编号是内容的一部分(比如「第一步:注册」),务必在 HTML 里也写出来,或补 `aria-label`,别让信息只活在 CSS 里。
  4. 现代浏览器已支持 `counter-reset: item reversed(10)` 做反向倒计数,但旧内核兼容性一般,正式项目建议先测目标环境。

什么时候该用它

结论:凡是「条目数量会变、编号要连续」的重复结构,都值得交给 CSS 计数器。

典型场景有三类:一是列表自动编号,比如答题选项、排行榜名次;二是多级目录,用 `counters()` 输出 2.3.1 这种层级号;三是后台渲染的表行号、论坛楼层号、问答聚合页里 FAQ 的序号——只要它们是同一个 DOM 结构循环渲染出来的,编号就不需要后端再算一遍序号字段,也不需要前端 `forEach` 时手动拼 index。条目被删除、排序被调整时,编号跟着 DOM 自动重排,永远不会出现断号或重号。

需要提醒的是,计数器只负责「显示层编号」,不改变 DOM 顺序,也不生成可被爬虫抓取的文本。如果你需要编号参与 SEO 或数据导出,仍要在服务端把序号落成真实文本。

一句话收束:`counter-reset` 起头、`counter-increment` 步进、`content: counter()` 露面,多级用 `counters()`,格式靠第二个参数,避开 `display: none` 和纯伪元素承载信息这两个坑,自动编号这件事就不用再写一行业务代码了。

本文转载自 Clara轻量论坛系统,原文地址:https://www.leleweb.cn/thread-421.html
转载请注明出处,版权归原作者所有。

全部回复 0

还没有回复,来抢沙发~