scss中选择器含.、#、:、[、]等css分隔符时必须手动转义,如.icon\.heart、#user\:profile;变量与插值需预先双反斜杠转义,:deep()内规则不变,bem需用@at-root配合转义生成扁平类名。

SCSS里写.icon.heart或#user:profile会直接编译失败,不是语法糖没开对,是CSS规范本身不认这种写法——必须手动转义。
哪些字符必须在选择器里转义
CSS把.、#、[、]、:、+、~、>、空格全当作分隔符或逻辑符号。只要它们出现在类名、ID、属性值里,就得加反斜杠。
-
class="icon.heart"→ 必须写.icon\.heart(点号转义) -
id="user:profile"→ 必须写#user\:profile(冒号转义) -
data-id="s0-1-17-5[2]"→ 必须写[data-id="s0-1-17-5\[2\]"](方括号转义) - 嵌套中用插值拼接时,转义要双写:
[#{$attr}="s0-1-17-5\[\2\]"]
Vue的:deep()里转义更易翻车
:deep()只是伪选择器,它包裹的内容仍是原生CSS,规则一条不少。
-
::deep(.el-input__inner[data-v-123456[active]])→ 直接失效,[active]没转义 - 优先改用带引号的属性值:
::deep(.el-input__inner[data-v-123456="active"]) - 若值动态且含不可控字符,放弃属性选择器,改用
:deep(.el-input__inner).active - 在
:deep()里用插值,变量内容必须已转义:$name: "user\:profile"; ::deep(.#{$name}) { }
SCSS变量和插值里的转义陷阱
SCSS变量存的是字符串字面量,不会自动帮你加反斜杠;插值也不触发转义逻辑。
- 写
$id: "user:profile"; .#{$id} { }→ 编译报错,:没被转义 - 正确做法:
$id: "user\:profile"; .#{$id} { }(变量里就存好转义) - 用
quote()处理非法开头的值:@each $key, $val in ("2xl": 2rem, "max-sm": 1rem) { .text-#{quote($key)} { font-size: $val; } } -
&不能补救父选择器本身的非法性:.user:profile { &:hover { }→ 错误在.user:profile定义阶段,不是&能兜住的
BEM场景下@at-root和转义的配合
想生成.card__header这类扁平类名,&__header会产出.card .card__header(带空格),必须用@at-root提级并确保转义干净。
-
.card { @at-root #{&}__header { color: #333; } }→ 输出.card__header - 若块名含特殊字符:
$block: "nav\.main"; @at-root #{$block}__item { } - 禁止在
&:hover或@media里套@at-root #{&}__xxx,输出顺序乱,语义也错 - 所有
__和--类名必须与块同级,HTML里少写一个card基础类,样式就彻底失效
最常被忽略的是:DevTools里看到“匹配到的元素”,未必是你写的那条规则生效的——可能只是其他同名类或全局样式覆盖了,而你还在调转义。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











