直接用counter-reset嵌套会断号,因为同名计数器在子作用域中被重置而非继承递增;需为每级定义独立计数器(如level1、level2),并在对应li上分别执行counter-increment,再通过content拼接counter(level1)和counter(level2)实现“1.1”格式。

为什么直接用 counter-reset 嵌套会断号?
因为 counter-reset 在每个作用域里重置的是同名计数器,不是“继承式递增”。比如你在 ol 里设 counter-reset: item,子 ol 再设一次 counter-reset: item,它就真把父级的 item 给清零了,而不是从父级当前值继续——结果就是二级列表永远从 1 开始,和一级编号无关。
真正要实现“1.1、1.2、2.1”这种效果,得靠多个独立计数器 + counter-increment 的叠加控制。
- 一级用
counter-reset: level1,二级用counter-reset: level2,互不干扰 - 每层
li都要同时做自己的counter-increment和父级的(比如二级li要increment level1和level2) -
counter()函数只能取当前作用域最近一次increment的值,不能跨层“读取”父级计数器状态
怎么写 CSS 才能让 ol 嵌套生成 1.1、1.2、2.1 这种格式?
核心是分层定义计数器,并在每一级 li 的 ::before 里拼接 counter(level1) 和 counter(level2),中间加点号。
ol {
counter-reset: level1;
}
ol ol {
counter-reset: level2;
}
ol li {
counter-increment: level1;
}
ol ol li {
counter-increment: level1 level2;
}
ol li::before {
content: counter(level1) ".";
}
ol ol li::before {
content: counter(level1) "." counter(level2) " ";
}
注意:第二层 li 必须同时 increment level1 和 level2,否则 level1 不会随嵌套项推进;而第一层 li 只 increment level1,避免干扰二级编号逻辑。
三级及以上怎么扩展?
每多一层,就多一个计数器名,多一套 counter-reset 和 counter-increment 规则。比如三级需要 level3:
- 新增
ol ol ol { counter-reset: level3; } - 三级
li写成ol ol ol li { counter-increment: level1 level2 level3; } -
::before改为content: counter(level1) "." counter(level2) "." counter(level3) " ";
别试图用 JS 或伪类动态生成层级名——CSS 计数器不支持变量或表达式,所有层级必须显式命名、显式声明。浏览器对超过 5 层嵌套的性能影响不大,但可维护性会快速下降。
IE 或旧版 Safari 下 counter() 不生效怎么办?
IE11 支持 counter-reset 和 counter(),但不支持多参数 counter(level, decimal) 的格式化(比如罗马数字),只认默认十进制;Safari 9+ 没问题,但 Safari 8 及更早版本对嵌套 counter-reset 有 bug,子列表可能全显示 0。
如果必须兼容 Safari ≤8,只能放弃纯 CSS 方案,改用 JS 动态写 data- 属性再用 CSS 读取,或者直接服务端渲染编号。
实际项目中,只要目标环境明确支持现代 CSS(Chrome 26+, Firefox 19+, Edge 12+, Safari 9+),这套写法稳定可靠;容易被忽略的是:每次新增嵌套层级,都要同步更新三处——counter-reset、counter-increment、content,漏一处就会断号或重复。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











