sass选择器中直接写.#{$var}会编译失败,因解析器要求选择器开头必须是字母、下划线或&,而插值在语法分析阶段未展开,被视为空起始;正确做法包括使用@each/@for循环、&结合@at-root、quote()包裹非法字符、避免@extend插值类名,以及用双层插值#{"@#{$name}"}生成含@符号的类名。

选择器里直接写 .#{$var} 会编译失败
这不是变量没定义的问题,而是 Sass 解析器在语法分析阶段就拒绝了这种写法。它要求选择器开头必须是字母、下划线或 &,而 #{$var} 在此时还没展开,被当成“空起始”处理。哪怕 $var: "primary" 已定义,.#{$var}-btn 也会报错:Invalid CSS after ".": expected selector, was "#{"。
真正能用的路径只有两个:
- 用
@each或@for循环,在每次迭代中让插值处于固定前缀之后(如.btn-#{$type}) - 在嵌套规则内,用
&引用父级 +@at-root提升作用域,避免生成意外嵌套结构
带破折号或数字开头的后缀必须 quote() 包裹
如果后缀来自 map 或 list,且含非法字符(如 "max-sm"、"2xl"),直接插值会导致 Sass 把破折号当减法、把数字开头当无效标识符,报错 Undefined variable "max" 或静默产出浏览器无法识别的选择器。
正确做法是显式调用 quote():
@each $key, $val in ("sm": 0.75rem, "max-sm": 0.625rem, "2xl": 2rem) {
.text-#{quote($key)} {
font-size: $val;
}
}
输出为 .text-"max-sm" 这类带引号类名——CSS 允许,浏览器可匹配,但部分 lint 工具会警告。不想引号?那就别让变量值含破折号或数字开头。
@extend 不能引用插值生成的类名
@extend 只认字面量选择器,不接受运行时拼接。写 @extend .btn-#{$state} 会直接报错:Invalid CSS after "@extend .btn-": expected "}", was "#{$state}"。
这意味着:
- 插值类名无法被其他规则复用,只能靠重复声明或改用
@mixin - 想实现类似 BEM 修饰符继承?得提前把所有可能的
$state值列进@each,再对每个生成的类单独@extend目标基类 - 调试时看不到插值结果对应的源码位置,因为最终 CSS 是字符串拼接产物,没有原始变量映射
双层插值 #{"@#{$name}"} 是响应式类名刚需
想生成 .text-sm@md 这种带 @ 符号的类名,单写 @#{$name} 会被 Sass 当成伪类解析(@md → :md),报错 Invalid CSS: was expecting a pseudo-class or pseudo-element。
必须用外层字符串包裹绕过解析:
@each $name, $width in (sm: 640px, md: 768px) {
@media (min-width: $width) {
.text-sm#{"@#{$name}"} {
font-size: 0.875rem;
}
}
}
这里 #{"@#{$name}"} 的外层 #{""} 强制转为字符串,内层 #{$name} 展开变量。破折号命名如 "max-sm" 插值后变成 .text-sm@max-sm,浏览器能识别,但某些工具链会警告 selector-no-unknown。
插值只做字符串拼接,不校验合法性,也不自动清理空格或补连字符。拼出 .btn #{$type}(中间有空格)会变后代选择器,.123-mod 会被浏览器忽略——Sass 不报错,你得自己盯紧输入和拼接逻辑。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











