CSS计数器无法直接使用自定义属性(如var(--num))驱动counter-increment,因其仅接受标识符或整数,不支持变量引用;正确方式是用counter-reset配合data属性或JS动态设置起始值。

不能直接用 CSS 自定义属性(--counter)驱动 counter-increment,这是常见误解的根源——CSS 计数器与自定义属性属于两套互不感知的机制。
为什么 --num 不能直接传给 counter-increment
CSS 自定义属性是字符串值,且不具备“可递增性”;counter-increment 只接受标识符(如 section)或带整数偏移的标识符(如 section 2),不接受变量引用。写成 counter-increment: section var(--num); 会直接失效,浏览器忽略该声明。
- DevTools 中能看到该行被划掉(invalid value)
- 即使
--num是3,也不会让计数器跳三步 - 这种写法在所有浏览器中均不生效,不是兼容性问题,而是语法非法
真正可行的动态编号:用 counter-reset + 元素层级控制起始值
若需“每个 .chapter 从指定数字开始编号”,应放弃用自定义属性驱动增量,转而用 counter-reset 在元素上显式重置计数器值。这需要你在 HTML 中通过 style 或 class 控制起始点。
.chapter {
counter-reset: section var(--start, 1); /* ❌ 无效!不能用 var() */
}
<p>.chapter {
counter-reset: section; /<em> ✅ 先清空 </em>/
}
.chapter[data-start="5"] {
counter-reset: section 4; /<em> ✅ 要显示 "5",就得重置为 4(因为 increment 才+1) </em>/
}
.chapter::before {
content: counter(section) ". ";
counter-increment: section;
}-
counter-reset: section N表示“下次counter-increment: section时,从N + 1开始” - 所以想显示
5,必须counter-reset: section 4 -
data-start属性比自定义属性更可靠——它可被 CSS 选择器匹配,且值能参与计算逻辑(通过预设 class 或 JS 注入)
需要 JS 协同的场景:编号依赖运行时数据
当编号来源是 API 返回、用户输入或 DOM 动态生成(比如表格行号随筛选变化),纯 CSS 无能为力。此时应让 JS 写入 counter-reset 值到 style 或 dataset。
立即学习“前端免费学习笔记(深入)”;
<ol class="dynamic-list"> <li>第一项</li> <li>第二项</li> </ol>
JS 示例:
const list = document.querySelector('.dynamic-list');
const offset = getStartNumberFromAPI(); // e.g., 100
list.style.counterReset = `list-item ${offset - 1}`;- 注意:这里减 1 是为了和
counter-increment: list-item的默认行为对齐 - 避免用
setAttribute('style', ...),优先用.style.xxx直接赋值,防止覆盖其他内联样式 - 若列表频繁重排,每次都要重新设置
counterReset,不能只设一次
最易被忽略的一点:CSS 计数器是**基于渲染树顺序**工作的,不是基于 DOM 顺序。如果用了 display: none、visibility: hidden 或 flex/grid order 移位,编号可能意外跳变或重复——调试时得打开开发者工具的“Layout”面板看实际渲染流,而不是只盯 HTML 结构。


















