SCSS中含.、#、[、]、:等字符的类名或属性选择器必须手动转义,否则编译失败或无法匹配;转义需紧贴字符加\,变量插值时内容须预先转义,:deep()内仍需遵守CSS转义规则,content双引号推荐用单引号包裹或十六进制转义。

SCSS里写含.、#、[、]、:等字符的类名或属性选择器,不转义就编译失败或根本匹配不到——这不是浏览器兼容问题,是CSS语法本身不认。
哪些字符必须手动加反斜杠转义
CSS规范把.、#、[、]、:、+、~、>、空格等全当作选择器分隔符或逻辑符号。一旦出现在类名、ID 或属性值里,就得用\挨个转义:
-
class="icon.heart"→ 必须写成.icon\.heart,不能直接.icon.heart -
id="user:profile"→ 写成#user\:profile,否则:profile被当成伪类解析 -
data-id="s0-1-17-5[2]"→ CSS里得写成[data-id="s0-1-17-5\[2\]"] - 转义必须紧贴字符:
\[有效,\[(带空格)无效
SCSS变量插值时如何安全拼接带特殊字符的选择器
用#{$var}动态生成选择器时,变量内容本身就得已转义,SCSS不会帮你补\:
- 错误写法:
$attr: "data-id"; [#{attr}="s0-1-17-5[2]"]→ 编译失败 - 正确写法:
$attr: "data-id"; [#{attr}="s0-1-17-5\[2\]"] - 更稳妥:把转义逻辑封装进变量:
$id: "user\:profile"; .#{$id} { color: red; } - 别依赖
@import外部未转义的SCSS片段——导入即编译,错误会静默吞掉整块样式
:deep()穿透中嵌套特殊字符的坑
Vue的:deep()只是伪选择器,它内部仍要遵守原生CSS规则,不是“免转义区”:
立即学习“前端免费学习笔记(深入)”;
-
::deep(.el-input__inner[data-v-123456[active]])直接失效,方括号没转义 - 先确认DevTools里实际渲染的HTML属性值是否真带
[和](右键→Edit as HTML) - 若值固定,优先用引号包裹:
::deep(.el-input__inner[data-v-123456="active"]) - 若值动态且含不可控字符,放弃属性选择器,改用
:deep(.el-input__inner).active这类class匹配
content属性里双引号怎么写才不报错
content值里的双引号最容易翻车,SCSS字符串解析器会提前吃掉\:
-
content: "\"Hello\""在Dart Sass下行为不稳定,不同版本可能编译出""Hello""或报错 - ✅ 正确做法一:用单引号包裹整个值,内部双引号不转义 ——
content: '"Hello"'; - ✅ 正确做法二:用十六进制转义 ——
content: "\201CHello\201D"; - ❌ 别写
content: attr(data-tip)带引号 —— 必须去掉外层引号,否则显示的是字面量attr(data-tip)五个字符
最常被忽略的一点:开发者工具里看到的“匹配到的元素”,未必是你写的那条规则生效的——可能只是其他同名类或全局样式覆盖了,得看Computed面板里的Specificity和来源路径才能准确定位。


















