CSS 计数器(手把手讲解)

什么是 CSS 计数器?它能帮你做什么?

在网页开发中,我们经常需要为页面中的标题、列表、章节编号等元素自动添加序号。传统的做法是手动写 <li> 标签或在 HTML 中插入数字,但这种方式既繁琐又容易出错。有没有一种方法,能让浏览器自动为元素“数数”呢?答案就是——CSS 计数器。

CSS 计数器是 CSS 提供的一种强大功能,它允许你通过样式规则自动递增编号,而无需在 HTML 中手动编写序号。你可以把它想象成一个“自动记账本”:你只需要告诉它“从 1 开始,每遇到一个新项目就加 1”,剩下的工作就由 CSS 自己完成。

这种技术特别适合用于文档结构清晰的页面,比如文章目录、教学笔记、技术手册等。更重要的是,它完全基于样式控制,不依赖 JavaScript,性能高且语义清晰。


CSS 计数器的基本语法与工作原理

要使用 CSS 计数器,你需要掌握两个核心属性:counter-resetcounter-increment。它们就像一对搭档,一个负责“初始化”,一个负责“递增”。

counter-reset:初始化计数器

counter-reset 用于在指定元素上创建一个计数器,并设置起始值。默认值是 0,但你可以自定义。

/* 为所有 h2 元素创建一个名为 section 的计数器,从 1 开始 */
h2 {
  counter-reset: section 1;
}

💡 注意:这里的 section 是你自定义的计数器名称。你可以起任何名字,比如 chapterstepitem 等,只要前后一致即可。

counter-increment:递增计数器

counter-increment 用于让计数器在每次匹配元素时增加指定的值。如果不指定值,默认为 1。

/* 每遇到一个 h2,section 计数器就加 1 */
h2 {
  counter-increment: section;
}

📌 小贴士:counter-increment 必须和 counter-reset 配合使用,否则计数器不会生效。


如何在内容中显示计数器值?

光有计数器还不行,你得让它“显示”出来。这就需要用到 content 属性和 counter() 函数。

content 与 counter() 函数

content 属性通常用于 ::before::after 伪元素,用来插入生成内容。而 counter() 函数就是用来获取某个计数器当前值的。

/* 在每个 h2 前面插入编号,格式为 "1. " */
h2::before {
  content: counter(section) ".";
}

✅ 这里的 counter(section) 返回当前 section 计数器的值,然后拼接上“.”符号。

完整示例:为标题自动编号

<article>
  <h2>第一章:初识 CSS</h2>
  <h2>第二章:布局基础</h2>
  <h2>第三章:响应式设计</h2>
</article>
/* 初始化计数器 */
h2 {
  counter-reset: section 1;
}

/* 每个 h2 触发一次递增 */
h2 {
  counter-increment: section;
}

/* 在每个 h2 前显示编号 */
h2::before {
  content: counter(section) ".";
  margin-right: 8px;
  font-weight: bold;
  color: #333;
}

效果预览: 1.第一章:初识 CSS
2.第二章:布局基础
3.第三章:响应式设计

🎯 这就是 CSS 计数器的魅力:你只需要写一次 CSS,所有标题自动编号,修改起来也极其方便。


多级计数器:实现嵌套编号结构

现实场景中,标题往往是嵌套的。比如:

  • 1.第一章
    • 1.1.第一节
    • 1.2.第二节
  • 2.第二章
    • 2.1.第一节

这时候就需要多级计数器了。CSS 支持嵌套计数器,只需为子元素重新 counter-resetcounter-increment

实现嵌套编号的步骤

  1. 在父级元素上重置子计数器
  2. 在子元素上递增父级计数器
  3. 在子元素上递增子计数器

示例代码:实现章节与小节编号

<article>
  <h2>第一章:基础语法</h2>
  <h3>1.1.选择器</h3>
  <h3>1.2.属性与值</h3>

  <h2>第二章:布局模型</h2>
  <h3>2.1.盒模型</h3>
  <h3>2.2.浮动与清除</h3>
</article>
/* 为 h2 初始化主章节计数器 */
h2 {
  counter-reset: subsection; /* 每个 h2 开始时重置 subsection */
  counter-increment: section; /* 主章节递增 */
}

/* 为 h3 递增子节计数器 */
h3 {
  counter-increment: subsection;
}

/* 在 h2 前显示主章节编号 */
h2::before {
  content: counter(section) ".";
  margin-right: 6px;
  font-weight: bold;
  color: #1a73e8;
}

/* 在 h3 前显示子节编号,格式为 "1.1" */
h3::before {
  content: counter(section) "." counter(subsection);
  margin-right: 6px;
  font-size: 0.9em;
  color: #555;
}

效果: 1.第一章:基础语法
1.1.选择器
1.2.属性与值
2.第二章:布局模型
2.1.盒模型
2.2.浮动与清除

🔍 妙处在于:counter-reset: subsection 会在每个 h2 后重新从 1 开始计数子节,实现了“每章独立编号”。


常见问题与实用技巧

1. 计数器不生效?检查这几点

  • 是否遗漏了 counter-reset
  • 是否在正确的元素上使用 counter-increment
  • content 属性是否使用了 ::before::after
  • 是否使用了 display: nonevisibility: hidden,导致伪元素无法渲染?

2. 如何自定义编号格式?

你可以使用 counter() 的第二个参数来指定计数器的样式:

h2::before {
  content: counter(section, upper-roman) ".";
}
格式类型 示例
decimal 1, 2, 3
lower-roman i, ii, iii
upper-roman I, II, III
lower-alpha a, b, c
upper-alpha A, B, C

✅ 这些格式支持在 counter() 中直接使用,无需额外 JS 或模板。

3. 计数器可以重置为任意值吗?

当然可以。counter-reset 接受第二个参数,表示起始值。

h2 {
  counter-reset: section 5; /* 从 5 开始 */
}

这在“从第 5 章开始”的文档中非常有用。


为什么推荐使用 CSS 计数器?

在现代网页开发中,我们常依赖 JavaScript 来实现动态编号,但这带来了额外的性能开销和维护成本。而 CSS 计数器的优势非常明显:

  • 零 JavaScript 依赖:纯 CSS 实现,无需加载脚本
  • 语义清晰:结构与样式分离,HTML 保持简洁
  • 易于维护:修改编号规则只需改 CSS
  • 支持打印样式:在打印页面时依然保持编号正确
  • 兼容性良好:现代浏览器均支持

📌 尤其适合静态文档、教学网站、技术博客等场景。


实战案例:为博客文章生成目录编号

假设你正在写一篇《CSS 从入门到精通》系列文章,每篇文章都有多个小节。你可以用 CSS 计数器自动为每节生成编号。

<section class="article">
  <h2>第一节:CSS 基础</h2>
  <h3>1.1.选择器</h3>
  <h3>1.2.属性详解</h3>
  <h2>第二节:盒模型</h2>
  <h3>2.1.边距与内边距</h3>
  <h3>2.2.盒类型</h3>
</section>
.article h2 {
  counter-reset: subsection;
  counter-increment: section;
}

.article h3 {
  counter-increment: subsection;
}

.article h2::before {
  content: counter(section) ".";
  font-weight: bold;
  margin-right: 8px;
  color: #d35400;
}

.article h3::before {
  content: counter(section) "." counter(subsection);
  font-size: 0.9em;
  color: #666;
  margin-right: 6px;
}

这样,你的文章目录就自动编号了,无论增加多少节,都不用手动改 HTML。


总结

CSS 计数器虽然不像 Flex 或 Grid 那样“热门”,但它是一个被低估的实用工具。它用极简的代码实现复杂的编号逻辑,真正体现了“样式驱动内容”的理念。

从单级编号到多级嵌套,从数字到罗马字母,CSS 计数器都能轻松应对。它不依赖 JS,不破坏语义,运行高效,是构建结构化文档的绝佳选择。

如果你还在为每个标题手动加序号而烦恼,不妨试试 CSS 计数器。它可能不会让你惊艳,但一定会让你省心。

记住:好的代码,不是写得多,而是用得巧。 而 CSS 计数器,正是这种“巧”的典范。