CSS计数器需先用counter-reset初始化,再用counter-increment递增,编号通过content: counter()在::before/::after中显示;嵌套需独立命名与重置,IE8不支持样式参数。

如何用 counter-reset 和 counter-increment 启动计数器
CSS Counter 的核心不是自动编号,而是手动声明“从哪开始数”和“每次在哪加一”。必须在父容器(如 ol、ul 或任意块级元素)上设置 counter-reset,否则 counter-increment 无效。
常见错误是只写 counter-increment: item; 却忘了初始化。比如给自定义列表编号:
ul.custom-list {
counter-reset: item; /* 必须先重置,否则不生效 */
}
li {
counter-increment: item; /* 每个 li 触发 +1 */
}
注意:counter-reset 的值默认为 0,但可指定起始数字,例如 counter-reset: item 5; 表示从 6 开始显示(因为第一次 counter-increment 后才取值)。
如何用 content: counter() 插入自定义编号
编号实际显示靠伪元素的 content 属性,且只能用于 ::before 或 ::after。直接写在 li 上不会渲染。
关键点:
-
counter(item)输出纯数字;counter(item, lower-roman)可切换样式(支持decimal、lower-alpha、upper-roman等) - 多个计数器可嵌套,例如侧边栏目录常用
counter(chapter) "." counter(section) - 若想加前缀/后缀,必须拼在
content里:例如content: "Step " counter(item) ":";
示例:带括号和空格的编号
li::before {
content: "(" counter(item) ") ";
margin-right: 8px;
}
为什么嵌套列表的编号会错乱?——作用域与重置位置
CSS 计数器是作用域化的:子元素继承父计数器,但若子容器也写了 counter-reset,就会覆盖并重新开始计数。这既是特性也是坑点。
典型问题场景:
- 多级菜单中,二级
ul忘记重置自己的计数器,导致编号接续一级 - 用
counter-reset: item;放在li上而非外层ul,结果每个li都从 1 开始 - 使用
display: none的li仍参与计数(counter-increment在渲染前执行)
修复方式:明确层级关系,例如二级列表用独立名称
ul.level-2 {
counter-reset: subitem;
}
ul.level-2 li {
counter-increment: subitem;
}
ul.level-2 li::before {
content: counter(item) "." counter(subitem) " ";
}
兼容性与替代方案:哪些老浏览器不支持?
counter() 在 IE8+、Edge 12+、Chrome 2+、Firefox 1+ 中都支持,但有两点限制:
- IE8 不支持
counter(name, style)的第二个参数(即不能用字母或罗马数字,只能数字) - 所有浏览器都不允许在非伪元素中用
content,所以无法通过 JS 动态读取当前计数值(它只存在于渲染树,不可脚本访问) - 若需动态控制(比如跳过某项、倒序),必须用 JS 操作
counter-increment的值或改用内联文本
真正容易被忽略的是:计数器不响应 DOM 动态插入。用 JS 添加新 li 后,只要它匹配选择器,就会自动触发 counter-increment —— 这点其实很可靠,不必手动更新。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











