counter-reset与counter-increment必须成对使用:前者在父容器初始化计数器(如counter-reset: section;),后者在子元素触发递增(如counter-increment: section;),再通过::before+content: counter(section)显示编号;计数器名区分大小写,嵌套需用counters()并确保每层作用域正确。

counter-reset 和 counter-increment 怎么配对用?
自动编号的核心是两个声明配合:用 counter-reset 初始化计数器,再用 counter-increment 在匹配元素上递增。它们必须成对出现,且作用域要对得上——counter-reset 通常放在父容器(比如 ol 或自定义 div),counter-increment 放在要编号的子元素(比如 li 或 section)。
-
counter-reset的值默认从 0 开始,但可以指定初始值,例如counter-reset: section 1让编号从 1 起步 -
counter-increment可以带步长,比如counter-increment: section 2实现隔项编号 - 同一元素可同时递增多个计数器:
counter-increment: section chapter - 计数器名区分大小写,且不能含空格或特殊符号(只允许字母、数字、短横线)
如何用 ::before 生成编号内容?
编号本身不显示,必须靠 ::before 伪元素 + content 插入。关键点在于用 counter() 函数读取当前值,它只接受计数器名作为参数,不支持表达式或拼接。
- 正确写法:
content: counter(section) ". " - 错误写法:
content: "第" counter(section) "节"(CSS 不支持字符串拼接) - 如需多级编号(如 2.3.1),要用
counters(),并配合嵌套的counter-reset,例如counters(section, ".") -
counter()第二个参数可设样式:counter(section, upper-roman)输出罗马数字
为什么嵌套列表编号会错乱?
常见问题不是语法写错,而是计数器作用域没理清。CSS 计数器是“块级作用域”,每个 counter-reset 会创建新作用域,子元素默认继承父级计数器值,但不会自动重置。
- 如果父容器用了
counter-reset: item,子列表又写了counter-reset: item,就会覆盖而非延续编号 - 解决嵌套编号,应避免在子容器重复
counter-reset,改用counter-increment维持递增,或用不同计数器名(如subitem) - 想让子列表从 1 重新开始,必须显式写
counter-reset: subitem,且确保该声明作用于子容器自身,而非它的父元素 - 浏览器对
counters()的层级识别依赖 DOM 嵌套结构,扁平化布局(如用display: flex打乱 DOM 顺序)会导致编号断裂
和 HTML
有什么实际区别?
是语义化原生方案,counter 是纯样式控制。两者最大差异在可访问性和行为一致性上。
- 屏幕阅读器通常能正确朗读
的序号,但对counter生成的编号可能完全忽略(除非额外加aria-label) -
支持start属性和reversed,counter需手动模拟(比如用负步长或 JS 辅助) -
counter可用于非列表元素(如标题、卡片、表格行),仅适用于语义列表 - 若页面有 JS 动态增删元素,
编号自动更新,counter依赖 CSS 重排,一般也正常,但极端情况(如 display: none 切换)可能滞后
复杂点不在写法,而在判断:这个编号是否需要被辅助技术感知?是否跨组件复用?是否与 DOM 结构强耦合?这些决定了该用语义标签还是 CSS 计数器。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











