css类名冲突根源在于其无作用域本质,css modules通过构建时哈希重命名(如.button→_button_abc123)实现真正隔离,需以.module.css为后缀、用import styles from './x.module.css'访问,硬写class="button"无效。

类名冲突不是命名不规范,是 CSS 本身没作用域
CSS 规范从设计上就不存在“局部作用域”概念。只要两个 .btn 出现在同一页面的样式表中,浏览器就会按层叠规则(source order + specificity)决定谁生效——没人能靠“约定”或“文档”阻止别人写一个权重更高的 .btn:hover 覆盖你。微前端、iframe 嵌入、第三方 SDK 加载顺序不可控,这类冲突不是偶发 bug,而是必然结果。
CSS Modules 不是加前缀,是构建时重命名
它把 .button 编译成类似 _button_abc123 这样的唯一哈希名,哈希值由「文件路径 + 原始类名 + 当前模块内样式内容」共同决定。所以:
-
Button.module.css里的.button和Modal.module.css里的.button生成的最终类名一定不同 - 改一行 CSS 或挪动文件位置,哈希就变——这是为了防止缓存误命中,不是 bug
- 这个过程发生在构建阶段(Webpack/Vite),纯 HTML 引入
.css文件完全无效
必须通过 JS 对象访问类名,硬写 class="xxx" 就等于没用
导入语句 import styles from './X.module.css' 返回的是一个对象,比如 { button: '_button_abc123', disabled: '_disabled_def34' }。常见错误包括:
- 还在 JSX 中写
class="button"或className="button"→ 样式完全不生效 - 用
require('./X.module.css')替代import→ 返回结构不同,styles.button可能是undefined - 文件后缀不是
.module.css(比如写成.css)→ loader 不触发,类名原样输出
全局样式要显式声明,否则自动被隔离
CSS Modules 默认只处理模块内类选择器,html、body、第三方库类(如 .hljs)全都不生效。必须用 :global() 包裹:
:global(.hljs) { background: #2d2d2d; }
:global(html, body) { margin: 0; }
漏掉 :global() 是引入语法高亮、图表库时最常踩的坑;TypeScript 项目还必须补 declare module '*.module.css' 声明,否则类型报错。
:global()、或者在非构建环境里硬套,它就立刻退化回普通 CSS。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











