CSS选择器中.、#、:、[、]、+、~、>、空格等必须用\转义;SCSS变量需预转义;:deep()内仍需转义;JS中须用CSS.escape()。

哪些字符在CSS选择器里必须转义
CSS把 .、#、:、[、]、+、~、>、空格全当作语法分隔符,不是类名的一部分。只要它们出现在类名或ID值里,就必须用反斜杠 \ 显式转义。
常见错误现象:.icon.heart 直接编译失败,浏览器报 Invalid selector;#user:profile 被当成 ID 选择器加伪类,根本匹配不到 id="user:profile" 的元素。
-
class="icon.heart"→ 必须写成.icon\.heart -
id="user:profile"→ 必须写成#user\:profile -
data-id="s0-1-17-5[2]"→ 必须写成[data-id="s0-1-17-5\[2\]"]
SCSS中变量插值时的双重转义陷阱
SCSS变量不自动转义,插值 #{} 也不触发转义逻辑。写 $id: "user:profile"; .#{$id} { } 会直接报错——冒号没被处理。
正确做法是:转义动作必须提前落在变量定义阶段。
立即学习“前端免费学习笔记(深入)”;
- 手动双写反斜杠:
$id: "user\:profile"; .#{$id} { color: red; } - 对非法开头的值(如数字开头),用
quote()包裹:.text-#{quote("2xl")} { font-size: 2rem; } - 别指望
&补救:.user:profile { &:hover { } }错误发生在父选择器声明时,&无法覆盖语法错误
:deep() 伪选择器里的转义失效场景
:deep() 不是 SCSS 特性,它只是 Vue 提供的穿透封装,包裹的内容仍是原生 CSS,所有转义规则照旧生效。这里最容易翻车。
典型错误:::deep(.el-input__inner[data-v-123456[active]]) —— 方括号没转义,整个规则被忽略。
- 优先改用带引号的属性值:
::deep(.el-input__inner[data-v-123456="active"]) - 若值动态且含不可控字符,放弃属性选择器,改用组合类:
:deep(.el-input__inner).active - 非得用插值时,变量内容必须已转义:
$name: "user\:profile"; ::deep(.#{$name}) { }
运行时动态拼接选择器必须用 CSS.escape()
JavaScript 中拼接 ID 或 class 到 querySelector 时,不能靠经验手写反斜杠。用户输入、API 返回值可能含任意字符,包括 Unicode、控制符、甚至 \0。
CSS.escape() 是唯一可靠方案,它按 CSS 规范生成合法标识符。
- 安全写法:
document.querySelector('.item[data-id="' + CSS.escape(id) + '"]') - 它会把
"user:profile"转成"user\:profile",把"foo.bar[baz]"转成"foo\.bar\[baz\]" - 不要省略它去“优化”性能——DOM 查询失败的代价远高于一次字符串处理
真正容易被忽略的是:转义不是可选项,是 CSS 语法层的硬性要求。无论你用 SCSS、Vue、JS 拼接,还是手写原生 CSS,只要选择器里出现分隔符字符,就必须转义。漏掉一个 \,轻则样式不生效,重则整条规则静默丢弃。


















