css modules 依赖文件名(如 button.module.css)、正确导入(import styles from './x.module.css')和动态绑定(classname={styles.button})三要素,任一出错即静默退化为全局样式。

文件名必须带 .module.css 后缀
CSS Modules 不是靠配置开关启用的,而是构建工具(如 CRA、Vite)按文件名自动识别的。只要文件名不匹配 .module.css(或 .module.scss、.module.less),就完全不会走模块化流程,样式会静默变成全局注入——且不报错。
常见错误包括:Button.css、Button.modules.css(拼写错误)、Button.Module.CSS(大小写不一致在 macOS/Linux 下也失效)。正确命名只有:Button.module.css。
注意:CRA 默认只识别 /\.module\.(css|sass|scss|less)$/,其他后缀需手动配 loader。
导入必须写成 import styles from './X.module.css'
这是最常踩的坑:用 import './X.module.css' 或 import * as styles from './X.module.css' 都不行。
-
import './X.module.css'→ 样式生效,但类名不哈希,退化为全局 CSS -
import * as styles from './X.module.css'→ 在 CRA 中返回空对象,styles.xxx全是undefined -
import styles from './X.module.css'→ ✅ 唯一正确方式,styles是一个普通 JS 对象,键为原始类名,值为哈希字符串(如Button_button__kx9f2)
TS 项目还需补类型声明,否则 styles.xxx 报错:declare module '*.module.css' { const classes: Record<string string>; export default classes; }</string>
类名必须通过 styles.xxx 动态绑定
className={styles.button} 是唯一合法用法。任何绕过 styles 对象的写法都会破坏模块化:
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
-
className="button"→ 全局查找.button,找不到,样式丢失 -
className={styles['btn-' + type]}→ TS 编译可能通过,但运行时styles['btn-primary']是undefined,最终className="undefined" -
styleName="button"→ 这是react-css-modules的旧语法,与原生 CSS Modules 不兼容
动态组合推荐用 clsx:className={clsx(styles.button, props.primary && styles.primary)},它会自动过滤 undefined 和空字符串。
:global() 不是快捷通道,而是逃生舱
:global() 只应在必要时穿透作用域,比如重置第三方组件样式或对接遗留 CSS。滥用会让模块化形同虚设。
合法写法::global(.ant-btn) { margin: 0; } 或 .container :global(.icon) { color: blue; }。
非法写法:.btn { :global(.icon) { ... } } —— 嵌套语法不被解析,编译后无效;更危险的是把整个规则包进 :global(),等于白写 .module.css。
真正需要全局样式的,应该单独建 base.css 并用 import './base.css' 引入,和模块化样式天然隔离。
文件名、导入写法、类名访问这三处任一环节出错,CSS Modules 就彻底失效,而错误极其安静——没有警告、没有报错、只默默漏掉样式。调试时先确认这三点,比查半天 DOM 更快。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










