直接用.btn类名必污染全局,因浏览器只按选择器匹配、权重和加载顺序生效,无模块隔离;bem需遵守元素不嵌套、修饰符依附基础类等硬约束;css modules泄漏多因动态拼接错误、:global滥用或第三方dom不可控。

直接用.btn这类泛化类名为什么一定会污染全局
浏览器根本不关心你写在哪个文件里,只看选择器是否匹配、权重多少、加载顺序。.btn在header.css里定义一次,在footer.css里再定义一次,后加载的就生效——没人管你是不是想复用还是想隔离。.btn这种名字没有归属感,.header-btn也不够,因为“header”不是模块边界,只是位置描述。真正起作用的是语义锚点,比如search-form__submit,它天然绑定到search-form这个功能块,脱离上下文就失去意义。
BEM命名中容易被忽略的三个硬约束
很多人写了block__elem就以为合规了,但实际落地时踩坑最多的是这三条:
-
search-form__input合法,.search-form input非法——后者依赖HTML层级,父容器一改就失效,且会误中其他input -
button--primary必须和button同时存在,单独写button--primary是错的——修饰符不是独立类,它需要基础结构支撑 -
page__section__title违反BEM——元素不能嵌套元素,应拆成page__section和section__title两个独立块
CSS Modules启用后仍出现样式泄漏的常见原因
开了modules: true不代表万事大吉,泄漏往往发生在边界处:
- 动态拼接类名时写错:
cls + '__icon'漏掉下划线,变成buttonicon而非button__icon,构建后无法匹配哈希类 - 用了
:global(.ant-select-selector)但没加限定范围,结果所有.ant-select-selector都被改了 - 第三方组件内部DOM结构不可控,比如
dangerouslySetInnerHTML插入的HTML带class="highlight",这类类名不会被Modules处理
第三方UI库(如Ant Design)样式隔离最务实的做法
别指望靠BEM或Modules完全接管.ant-*类,它们是库自带的、不可变的。真正可控的是你的作用域入口:
- 给外层容器加唯一属性:
<div data-scope="user-profile">...</div>,然后写[data-scope="user-profile"] .ant-input - 避免模糊匹配:
[class*="ant-"]会误伤自定义类名含ant的元素,优先用[class^="ant-"]或精确data-scope - 服务端渲染静态HTML时,若无法控制
class,在外层加BEM块名,再用.user-profile [class^="hljs-"]兜底
card__title被另一处article-title的margin撑开,才明白:隔离效果不取决于你写了多少__和--,而取决于所有相关样式是否**只通过这个唯一类名注入**。只要某处还写着.header .logo,沙箱就已经漏了。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











