Dart Sass不支持:has()、:is()等新CSS选择器,是因为它只负责将SCSS转为CSS字符串,不校验CSS合法性;这些伪类必须作为完整选择器使用,不可在&后拼接,应交由PostCSS处理。

为什么Dart Sass不支持:has()、:is()等新CSS选择器
Dart Sass本身不是CSS解析器,它只负责把SCSS/Sass语法转成标准CSS字符串,不校验生成的CSS是否合法。所谓“无法识别最新CSS语法”,其实是你在@use或@forward中写了:has()这类选择器,而Dart Sass误判为非法嵌套结构——因为它仍在用旧规则解析“选择器上下文”。真正的问题不在Dart Sass,而在你混用了预处理器逻辑和原生CSS特性。
常见错误写法:
.card {
&:has(.badge) { // Dart Sass 会尝试把它当嵌套解析,但 :has() 不是 SCSS 语法
padding: 1rem;
}
}
- 这不是语法错误,而是语义错位:Dart Sass期望
&后面接的是合法SCSS选择器片段(如&__title),而不是浏览器才理解的运行时伪类 - 所有以
:开头的现代伪类(:is()、:where()、:has())必须作为完整选择器出现,不能放在&后参与拼接 - 若强行保留,需用引号包裹并禁用插值,例如:
"&:has(.badge)",但此时已失去SCSS嵌套意义
PostCSS才是处理新CSS语法的正确位置
把:has()这类特性交给PostCSS处理,才是符合工具链分工的做法。Dart Sass输出纯CSS后,由PostCSS + postcss-selector-parser和postcss-preset-env来识别、降级或透传新语法。
关键配置点:
- 确保
postcss.config.js中启用了postcss-preset-env,且stage设为4(支持所有已进入CR阶段的CSS特性) - 不要在Sass里写
@supports (selector(:has(*)))——selector()函数是CSS功能查询,不是Sass函数,Dart Sass会直接报Undefined function - 若需条件编译,改用
@if配合变量判断,例如:@if $supports-has { ... },再由构建脚本注入该变量
升级Dart Sass后反而报更多CSS语法错误?检查你的loader链
Vue CLI、Vite或Webpack中,Sass和PostCSS的执行顺序错了,会导致新CSS特性在到达PostCSS前就被Dart Sass当成无效内容拦截。
典型错误链:
SCSS → dart-sass → CSS → css-loader → PostCSS
正确顺序应为:
SCSS → dart-sass → CSS → PostCSS → css-loader
- Vite用户:确认
vite.config.ts中css.preprocessorOptions.sass未覆盖默认PostCSS流程 - Vue CLI用户:检查
vue.config.js里的css.loaderOptions.sass是否意外禁用了additionalData或implementation导致PostCSS被跳过 - Webpack用户:重点看
module.rules中scss规则的use数组,postcss-loader必须在sass-loader之后、css-loader之前
别让Sass编译器承担它不该干的活
最常被忽略的一点:Dart Sass的使命只是“预处理”,不是“CSS验证器”或“兼容性网关”。当你看到Invalid CSS after "}"却实际写了:has(),那说明你正把PostCSS该做的事塞给Sass做。
真正需要检查的不是Sass版本,而是三件事:
- 新CSS特性是否出现在
style标签内原生CSS块中(✅ 正确) - 还是被裹在
&、@at-root、@if等Sass控制结构里(❌ 错误) - 构建流程中PostCSS是否真的运行了,以及它的
browserslist配置是否覆盖目标环境
工具各司其职,错位使用只会放大问题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











