css counters 必须通过 counter-reset 初始化计数器并定义作用域起点,再用 counter-increment 触发递增,最后由 counters() 函数在 ::before 中拼接层级编号;缺一不可,否则编号错乱、跳号或全为0。

CSS Counters 本身不依赖 HTML 编辑器,但你在任何编辑器里写 HTML + CSS 时,只要浏览器支持,就能生效;关键不是编辑器功能,而是你写的 counter-reset 和 counter-increment 是否匹配嵌套结构。
为什么直接用 ol 嵌套经常编号错乱
原生 ol 在多层嵌套时默认只做“局部重置”,比如子 ol 会从 1 开始,但不会自动拼接父级编号(如 2.1、2.2)。CSS Counters 能补上这个缺口,但必须手动定义层级关系。
- 浏览器对
ol[type="1"]的嵌套有默认行为,但不可控、不跨浏览器一致 - 一旦混用
ul和ol,或中间插入非列表元素,编号极易断裂 -
counter-increment必须作用在实际渲染的元素上(比如li),不能只写在ol上就指望子项继承
正确绑定层级:用多个 counter 名称 + counter() 拼接
每个嵌套层级用独立 counter 名(如 section、subsection),再用 counter(section) 和 counter(subsection) 组合生成 1.1 这类格式。
ol {
counter-reset: section;
}
ol ol {
counter-reset: subsection;
}
li::before {
counter-increment: section;
content: counters(section, ".") " ";
}
ol ol li::before {
counter-increment: subsection;
content: counters(section, ".") "." counters(subsection, ".") " ";
}
-
counters()第二个参数是分隔符,不是字符串拼接——它会自动为每一级插入该字符 - 必须给每级
li单独设counter-increment,否则子级不会累加 - 如果某级想跳过编号(如仅展示标题不编号),就别给它加
counter-increment,也不要写::before
常见错误:CSS 选择器没覆盖到真实 DOM 结构
很多人写完 CSS 发现编号还是 1、1、1,问题往往出在选择器没命中目标 li。尤其当编辑器自动生成 wrapper 元素(如 div.editor-content)或用了 Shadow DOM 时,CSS 作用域会被切断。
- 检查浏览器开发者工具里,
li元素是否真的被你的li::before规则匹配到(看 computed 标签页) - 如果编辑器输出的是
<ol><li><p>内容</p></li></ol>,那li::before有效;但若输出<li><div>内容</div></li>,且div有display: block,可能遮挡伪元素视觉效果 - 避免用过于宽泛的选择器如
*::before,容易被编辑器注入的其他样式干扰
真正难的不是语法,是确认你的 HTML 输出结构和 CSS 选择器之间有没有“看不见的断层”——比如编辑器悄悄包了一层 span,或者把 li 渲染成 custom-li 自定义标签却忘了加对应样式。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











