React项目推荐用CSS Modules,因其在构建时将.button重命名为Button_button__Kx2f1等带文件标识和哈希的唯一类名,从源头杜绝样式污染;失效主因是文件后缀非.module.css、路径错误、构建配置缺失或硬写class,验证方式为DevTools中查看class是否含哈希值。
React项目中用CSS Modules避免全局样式污染,核心就一条:让每个类名在构建时变成带文件标识和哈希的唯一值。只要文件后缀、导入路径、构建配置三者对齐,样式就天然隔离——不是靠人盯人防冲突,而是物理上没机会撞上。
这不是 React 报错,是构建阶段压根没生成 styles 对象。常见原因:
Button.css 或 Button.module.scss 这类后缀不对——必须是 .module.css(或 .module.less,但需配对应 loader)import styles from './Button.module.css' 路径写错,或者大小写不一致(macOS/Linux 下 button.module.css ≠ Button.module.css)css-loader 的 modules: true 配置;Vite 项目用了 .css 后缀却指望模块化生效dangerouslySetInnerHTML 里硬写了 class="button"——模块类名只存在于 JS 对象中,不会自动注入全局验证是否启用:打开 DevTools 查看元素 class 属性,看到 Button_button__Kx2f1 这类就是对的;如果还是原始 button,说明 CSS Modules 根本没走通。
写 className={`${styles.button} ${styles[variant]}` 很容易翻车,因为 variant 值可能根本没在 CSS 文件里定义。
立即学习“前端免费学习笔记(深入)”;
styles[variant] ?? '' 或 styles[variant] || ''
const { primary = '', large = '' } = styles;
styles['large'] 在构建时若不存在,值就是 undefined,不是空字符串:global() 是唯一能“逃逸”模块作用域的方式,但边界必须清晰:
:global(.ant-modal) { z-index: 9999; }(覆盖第三方库)、:global(*) { box-sizing: border-box; }(重置基础样式):global();在子组件里用它去“修复”父组件没导出的类名;当成 BEM 命名的替代方案@import './reset.css' 进模块文件,导入的仍是全局 CSS,等价于直接写 :global(),不是“安全引入”不是 bug,是设计使然。哈希基于文件路径、内容、甚至构建顺序生成,改一行 CSS 或挪动文件位置都会触发更新。这对缓存和热更新其实是有利的,但要注意:
Button_button__abc123 这种选择器——应该用 data-* 属性或测试专用 class真正容易被忽略的点是:CSS Modules 解决的是类名冲突,但对 body、html 或全局伪类(如 :focus-visible)这类规则依然无能为力——它们天生就该全局生效,得靠路由级样式清理或 CSS-in-JS 方案兜底。