Stylelint 默认不检测废弃 CSS 变量,因其仅校验语法与格式,无法构建变量声明-引用的 AST 关系;CSS 变量(--foo)属运行时作用域,需借助 PostCSS AST 手动提取声明与使用并比对,或通过插件(如 stylelint-plugin-no-unused-css-vars)定制扩展,且 SCSS/JSX 中定义的变量须前置处理才能纳入分析。

为什么直接用 stylelint-config-standard 无法检测废弃 CSS 变量
Stylelint 默认只校验语法、格式和基础规则(比如 declaration-block-no-duplicate-properties),它不跟踪变量定义与引用关系。CSS 变量(--foo)是运行时作用域机制,没有 AST 级别的“声明-使用”双向索引,所以原生规则无法判断某个 --old-theme-color 是否在任何地方被 var(--old-theme-color) 引用过。
必须自己构建变量引用图:先收集所有 :root 或 @property 中的 --* 声明,再遍历所有 var(--*) 调用,最后取差集。
如何用 PostCSS AST 提取并比对 CSS 变量声明与使用
Stylelint 插件本质是 PostCSS 插件,所有逻辑基于 postcss 的 Root、Rule、Declaration、CustomProperty 等节点。关键不是写 CSS 解析器,而是复用 PostCSS 已解析好的结构。
- 声明提取:遍历所有
Declaration节点,匹配prop以--开头,且父节点是:root或包含@custom-media等上下文(注意:不能只看:root,有些项目用.theme-light类做变量作用域) - 使用提取:遍历所有
Declaration和AtRule的params、value字符串,用正则/var\(--[\w-]+\)/g提取,再用postcss-values-parser更可靠地解析函数参数(避免误伤注释或字符串字面量) - 作用域处理:若项目用
@layer或嵌套类控制变量可见性,需记录每个变量的声明节点位置,并检查调用节点是否在同层或子层作用域内
stylelint-plugin-no-unused-css-vars 的核心实现要点
已有插件如 stylelint-plugin-no-unused-css-vars 并非开箱即用——它默认只扫描 :root,不支持 SCSS 变量注入、CSS-in-JS 字符串拼接、或通过 setProperty() 动态设置的变量。实际项目中必须定制。
- 禁用默认声明收集,改用
root.walkDecls(decl => { if (decl.prop.startsWith('--')) { ... } })并手动过滤掉/* stylelint-disable */注释块内的声明 - 对
value字段做多轮解析:先用postcss-values-parser解析,失败则 fallback 到正则;对calc(var(--a) + 1px)这类嵌套,要递归进functionNode子节点 - 输出报告时,用
result.warn()而非result.report(),否则会阻断后续规则执行;错误信息里必须带node.source?.start行号,不然 VS Code 插件无法跳转
如何让插件识别 SCSS/JSX 中定义的 CSS 变量
Stylelint 只处理 CSS 文件。如果变量在 variables.scss 里定义($primary: #007bff),或在 JSX 中通过 style={{ '--bg': 'red' }} 设置,这些根本不会进入 PostCSS AST。必须前置处理。
- SCSS 场景:用
stylelint-scss扩展插件,在scss-at-rule-arg钩子中捕获@define-mixin或$变量赋值,转换为虚拟 CSS 声明节点注入 AST - JSX 场景:启用
stylelint-processor-styled-components或自定义 processor,解析styled.div模板字面量,在css``块中提取--*字符串,生成模拟Declaration节点 - 动态 JS 设置:这类无法静态分析,只能约定规范(如禁止在
useEffect中调用el.style.setProperty('--x', ...)),靠 ESLint 规则no-restricted-syntax拦截
真正难的不是写插件,是厘清项目里 CSS 变量到底从哪来、到哪去。没理清数据流就写检测逻辑,90% 的“废弃变量”其实是漏掉了某处动态注入路径。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











