stylelint-selector-bem-pattern不报重复样式但强制bem结构,使语义重复(如多处定义.card__title)暴露更早;需配合selector-max-universal、declaration-block-no-duplicate-properties等规则及grep、ast、puppeteer等工具协同治理。

用stylelint-selector-bem-pattern配合自定义规则抓重复类名
它本身不报重复样式,但能帮你锁死BEM结构,让重复问题暴露得更早。比如两个文件都写了.card__title,且都定义了font-size: 1.25rem,这时stylelint-selector-bem-pattern虽不直接标红,但它强制要求所有card__title必须属于card块——你就能立刻意识到:这个元素是不是该抽成共享样式?
实操建议:
- 在
.stylelintrc.cjs里启用plugin/selector-bem-pattern并设preset: 'bem',确保所有__和--用法合法 - 加一条
selector-max-universal规则禁用*选择器,避免.card__title *这种模糊写法掩盖重复逻辑 - 配合
declaration-block-no-duplicate-properties规则,防止同一选择器里出现两次color
用grep或AST工具扫描跨文件重复声明
纯文本搜card__title可能漏掉Sass嵌套或CSS Modules编译后的类,真正有效的扫描得靠结构化匹配。
常见错误现象:_card.scss里.card__title { color: #333; },_user-card.scss里又有一份一模一样的.user-card__title { color: #333; }——这本质是语义重复,不是命名重复。
实操建议:
- 用
grep -r "card__title.*color" src/css/定位疑似重复区域,再人工比对是否真可合并 - 在VS Code里装
ESLint+stylelint-processor-html插件,把HTML模板也纳入扫描范围,查class="card__title"是否被多处引用却没统一来源 - 若用PostCSS,加
postcss-discard-duplicates插件,在构建阶段自动剔除完全相同的声明块(慎用,需确认无权重差异)
用Puppeteer快照+diff对比发现隐性重复
有些重复不体现在代码里,而藏在视觉表现中:比如button--primary和cta-button--active最终渲染出一模一样的背景色、边框、间距——人眼难辨,工具可测。
使用场景:重构后想确认有没有“写了两套样式,效果却一样”的冗余。
实操建议:
- 写一个脚本,用Puppeteer加载同一页面,分别注入旧CSS和新CSS,截取所有
button元素的screenshot - 用
pixelmatch比对两张图,设置threshold: 0(像素级一致),若差异为0,说明样式输出完全相同 - 重点盯
--large、--dark等修饰符组合:如果card__header--large和card__footer--large渲染效果一致,就该提取size-large工具类
为什么BEM本身不能防重复,反而容易藏重复
BEM解决的是作用域混乱,不是代码复用。一个card__title在10个组件里各写一遍,只要命名合规,stylelint就默许——它只管“名字对不对”,不管“值重不重”。
最容易被忽略的地方:修饰符--常被滥用为视觉开关,导致modal__close--large、tooltip__arrow--large、form__label--large各自定义font-size: 1.5rem,却不抽成text-lg工具类。
真正要卡住的点是:BEM类只负责“归属”,工具类才负责“复用”。二者必须共存,不能指望BEM单挑全部职责。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











