必须先在父元素设counter-reset初始化计数器,再在目标元素设counter-increment递增,最后在::before或::after中用content: counter(name)显示;单独写content: counter()无效。

content: counter() 在 ::before/::after 中怎么写才生效
必须配合 counter-reset 或 counter-increment 才能显示数字,单独写 content: counter(mycount) 会显示空值或字面量“counter(mycount)”。
常见错误是只加了 content 却忘了初始化计数器。计数器作用域默认是块级容器,通常得在父元素上设 counter-reset,再在子伪元素里用 counter() 引用。
-
counter-reset: section—— 在父容器(如<ol></ol>、<div class="list">)上声明,初始化名为 <code>section的计数器为 0 -
counter-increment: section—— 在每个要编号的子元素(如<h2></h2>、<li>)上递增,否则counter(section)始终返回 0 -
content: counter(section)—— 写在::before或::after的样式里,仅支持行内渲染,不能用于替换整个元素内容
如何给 h2 标题自动加 “1.”、“2.” 这样的序号
这是最常用场景:不依赖 <ol></ol>,纯 CSS 控制标题编号。关键在于把 counter-increment 放在 h2 自身,而不是它的父容器。
body {
counter-reset: heading;
}
h2 {
counter-increment: heading;
}
h2::before {
content: counter(heading) ". ";
font-weight: bold;
}
注意:counter-reset 放在 body 是为了覆盖整页;如果只希望某区块内独立编号,就改放在那个 <section></section> 上,并确保子 h2 确实是它的后代。
如果 h2 被包裹在 <div> 里且该 <code><div> 没有继承或重置计数器,编号可能中断或重复——这时要检查 DOM 层级和 CSS 选择器是否真正匹配到目标元素。
<h3>多级编号(如 1.1、1.2、2.1)为什么 nested counter() 不生效</h3>
<p><code>counter() 默认只取最近一级的值;要嵌套,必须用 counter(name, style) + counter-reset 的层级声明,且子计数器名需不同。
- 一级用
counter-reset: chapter,二级就得用counter-reset: section(不能也叫chapter) - 在子元素(如
h3)上同时写counter-increment: chapter section,表示它既推进章号,也推进节号 -
content: counter(chapter) "." counter(section)才能拼出 “1.1” - 若想让节号在章变更时归零,得在
h2上写counter-reset: section,否则section会全局累加
漏掉子级的 counter-reset 是导致 “1.5、1.6、1.7…” 而不是 “2.1” 的最常见原因。
兼容性和 content: counter() 的限制
IE8+、所有现代浏览器都支持 counter(),但有几个硬性限制容易被忽略:
-
content只在::before和::after伪元素中有效,不能用于其他伪类(如::first-line) - 无法在
attr()或字符串拼接中动态计算值,counter()返回的是纯文本,不能参与 CSS calc() - 计数器名区分大小写,
counter(MyCount)和counter(mycount)是两个不同计数器 - 如果元素被
display: none,它仍会触发counter-increment(除非用visibility: hidden)
真正在意语义化编号的场景(比如导出 PDF 或屏幕阅读器),还是优先用原生 <ol></ol> + <li>;CSS 计数器本质是视觉修饰,不改变 DOM 结构和可访问性树。











