counter-reset 和 counter-increment 在 Sass 中不能直接写在嵌套子规则里,因为计数器逻辑依赖浏览器运行时,必须由父容器顶层声明 reset、子项声明 increment 与 content 配合;Sass 仅生成 CSS 结构,不模拟计数行为。

为什么 counter-reset 和 counter-increment 在 Sass 中不能直接写在嵌套规则里
因为 CSS 计数器是纯 CSS 运行时机制,Sass 编译期不解析或模拟计数器行为。你写 counter-reset: mylist; 在 .item 里,Sass 不会报错,但最终生成的 CSS 会把重置逻辑放在每个 .item 上,导致编号永远从 1 开始——这不是你想要的。
关键点:计数器控制必须落在「容器」上,且只出现一次;编号渲染才放在「子项」里。Sass 只负责生成正确的 CSS 结构,不替代浏览器的计数器执行逻辑。
-
counter-reset必须写在有序列表父容器(如ol或自定义.list)的顶层规则中 -
counter-increment和content: counter(...)必须配对出现在伪元素(::before)中,不可省略content - Sass 的嵌套容易误导人把
counter-reset写进子选择器,这是最常见翻车点
用 Sass 变量和 @mixin 统一管理计数器名称与样式
硬编码 counter(list-1) 很难维护,尤其当页面有多个定制列表(目录、步骤、引用编号)。用 Sass 变量绑定计数器名,并封装为可复用的 @mixin,能避免拼写错误和重复声明。
$counter-name: list-step;
$list-counter-style: decimal;
@mixin list-counter($name: $counter-name, $style: $list-counter-style) {
counter-reset: #{$name};
> li {
counter-increment: #{$name};
&::before {
content: counter(#{$name}, #{$style}) ". ";
display: inline-block;
width: 2em;
margin-right: 0.5em;
text-align: right;
}
}
}
ol.step-list {
@include list-counter('step', lower-alpha);
}
- 变量
$counter-name确保重置与递增使用同一名称,避免因大小写或连字符不一致导致计数器失效 -
@mixin中用插值#{$name}保证输出为真实 CSS 标识符,而非字面字符串"list-step" - 不要在
@mixin外部再写counter-reset,否则会覆盖或重复——Sass 不合并同名声明,而是叠加输出
支持多级嵌套编号(如 1.1、1.1.1)时,counters() 函数怎么配合 Sass 使用
counters() 是 CSS 原生命令,Sass 无法增强它,但可以帮你安全生成带分隔符的调用。注意:它只接受字符串字面量作分隔符(如 "."),不能传变量——除非你用插值生成整个函数调用。
立即学习“前端免费学习笔记(深入)”;
ol.hierarchy {
counter-reset: section;
> li {
counter-increment: section;
&::before {
content: counters(section, ".") " ";
}
ol {
counter-reset: subsection;
> li {
counter-increment: subsection;
&::before {
content: counters(section, ".") "." counters(subsection, ".") " ";
}
}
}
}
}
- 嵌套层级越多,
counters()调用越容易漏掉括号或引号,建议用 Sass 循环 +@function生成,但简单场景手写更可控 - 分隔符必须是字符串,
counters(section, $sep)会编译失败;正确写法是counters(section, "#{$sep}") - 浏览器对
counters()的兼容性没问题(Chrome 2+、Firefox 1.5+、Safari 3.1+),但 IE8 及以下不支持——如果还要兼容,得用 JS 回退
为什么自定义字体或字号后编号经常错位,vertical-align 和 line-height 怎么调
编号由 ::before 生成,是行内元素,默认按基线对齐。一旦父 li 设置了大字号、行高或自定义字体,编号就会“吊”在文字上方或下沉,看起来像没对齐。
- 最稳方案:给
::before加vertical-align: middle或top,再微调margin-top - 避免依赖
line-height对齐——它受字体度量影响大,不同字体下表现不一致 - 如果编号用了等宽字体(如
font-family: 'SFMono-Regular'),加text-rendering: optimizeLegibility可改善小字号下的数字间距 - 调试时临时加
outline: 1px solid red到::before,能看清伪元素实际占位区域
计数器本身没有渲染问题,所有错位都来自伪元素的盒模型和对齐方式——这是最容易被当成“Sass 问题”却实际是 CSS 布局问题的地方。


















