在制作网页分页导航时,我们常常需要展示一串连续的数字页码,例如第一页到第十页。传统做法是在HTML里逐个写出数字,或者用脚本动态生成。其实CSS自带了计数器功能,可以让我们只写几个列表项,数字却自动按顺序出现。这种方式把编号逻辑完全交给样式层,结构更干净。

一、CSS计数器的基本原理
CSS计数器依赖两个核心属性:counter-reset和counter-increment。前者用于在特定元素上创建或归零一个计数器,后者用于在元素出现时让计数器增加。配合content属性与::before或::after伪元素,就能把当前计数值显示为文本。
计数器的名字由开发者自定义,同一个页面可以存在多个独立计数器。需要注意的是,计数器遵循文档流,只有被渲染的元素才会触发自增。如果某个元素被设置为display:none,它不会消耗计数。这一特性在计算可见页码时非常有用。
1.1 初始化与自增的语法
counter-reset写在父容器上,格式为counter-reset: 名称 起始值,起始值省略时默认为0。子项上写counter-increment: 名称 步长,步长省略时默认为1。以下代码展示了一个最简结构:
/* 父容器初始化计数器 page-num,从 0 开始 */
.pagination {
counter-reset: page-num 0;
list-style: none;
display: flex;
gap: 8px;
}
/* 每个子项让计数器加 1,并显示数字 */
.pagination li {
counter-increment: page-num 1;
}
.pagination li::before {
content: counter(page-num);
/* 具体样式省略 */
}
上面的例子中,第一个li在自增后值变为1,伪元素输出1;第二个变为2,以此类推。这样无需在HTML写死数字。
1.2 为什么适合分页导航
分页导航的本质是一组等样式的方块,区别仅在于序号。把序号交给计数器,意味着我们后续增加或减少页码节点时,不用手动改数字,也不会出现漏号、重号。对于后端模板循环输出空li的场景,前端自动编号可以大幅降低出错概率。
另外,计数器支持多种显示格式,比如十进制、罗马数字、字母序列。通过counter(name, lower-roman)这类写法,我们可以快速切换风格,而不必改动HTML。
二、构建分页导航的完整示例
下面给出一个可直接使用的分页导航代码。我们用nav包裹ul,列表项内部不放文字,完全靠伪元素显示编号,并加上链接与悬浮效果。
<nav class="page-nav">
<ul class="pagination">
<li><a href="?page=1"></a></li>
<li><a href="?page=2"></a></li>
<li><a href="?page=3"></a></li>
<li><a href="?page=4"></a></li>
<li><a href="?page=5"></a></li>
</ul>
</nav>
对应的CSS如下。我们在ul上重置计数器,在li上自增,并用::before把数字放到a标签内显示。同时做了基础美化:
.page-nav .pagination {
counter-reset: page-num 0;
list-style: none;
padding: 0;
display: flex;
gap: 6px;
}
.page-nav .pagination li {
counter-increment: page-num 1;
}
.page-nav .pagination li a {
display: block;
width: 36px;
height: 36px;
line-height: 36px;
text-align: center;
border: 1px solid #ccc;
border-radius: 4px;
color: #333;
text-decoration: none;
}
/* 用伪元素承载数字 */
.page-nav .pagination li a::before {
content: counter(page-num);
}
.page-nav .pagination li a:hover {
background: #f0f0f0;
border-color: #999;
}
这段代码的运行结果是五个带边框的方块,里面依次显示1到5。如果我们在HTML里再复制一个li,页面会自动出现6,完全不用改CSS逻辑。
有人可能会问:为什么不直接用ol有序列表?原因在于ol的编号样式可控性较弱,且默认带浏览器缩进与标记。用计数器可以精准控制数字出现在哪个伪元素、什么位置,也方便和Flex布局结合做居中排列。
2.1 高亮当前页
实际项目中通常要标记当前页。我们可以给对应的li加一个类,比如active,然后单独设置背景色。因为数字来自计数器,加类不会影响编号:
.page-nav .pagination li.active a {
background: #007bff;
border-color: #007bff;
color: #fff;
}
HTML里只需把第三页写成<li class="active">即可。计数器依旧输出3,但视觉上它被高亮,用户体验更清晰。
三、常见误区与注意事项
初学者容易把counter-reset误放到每一个li上,导致每次都重新从0开始,最终所有项都显示1。记住重置应放在共同父级,自增放在重复子级。
另一个误区是试图用content: counter(page-num);直接写在li而非伪元素上。根据规范,content只能用于::before和::after,普通元素设置无效。若想让数字成为元素真实文本节点,仍需要JS介入,纯CSS做不到。
3.1 嵌套计数器
如果分页里还有子分页,可使用counters()函数实现如1.1、1.2的层级编号。但对于普通数字分页导航,单层计数器已经足够,不必引入复杂度。
| 方案 | 维护成本 | 适用场景 |
|---|---|---|
| 手动写数字 | 高,易错 | 页码极少且固定 |
| JS渲染 | 中,需脚本 | 页码来自接口动态数据 |
| CSS计数器 | 低,纯样式 | 结构固定、样式驱动 |
通过上表可以看出,在结构稳定的后台列表页或文档站中,CSS计数器是性价比很高的选择。它把编号抽象为样式规则,让HTML只关心“有多少页”,而不是“每一页是几”。
四、总结
利用counter-reset与counter-increment,我们可以让分页导航的数字完全由CSS生成。这种做法减少了手写错误,也方便了后期维护。只要把握住父级重置、子级自增、伪元素输出这三个要点,就能轻松应对大多数数字样式需求。
当项目需要频繁调整页码数量但视觉风格统一时,不妨放弃写死数字,改用计数器方案,既简洁又专业。
CSS_countercounter-incrementpagination_style修改时间:2026-08-02 13:48:35