CSS Modules
CSS Modules 是一种基于构建工具的样式作用域方案,通过为类名生成唯一标识来实现组件级局部作用域。
#type / concept
#status / growing
#tech / dev / frontend
#resource / css
#resource / css-modules
[!info] related notes
- 所属 MOC: CSS MOC
- 前置概念: CSS
- 并列概念: BEM 命名规范, CSS-in-JS, Sass / SCSS
- 易混淆概念: Scoped 样式的作用域原理
- 关系笔记: 前端样式方案演进与选型
CSS Modules
一句话定义
CSS Modules 是一种构建期样式隔离方案:开发者写普通 CSS,构建工具把类名编译成唯一名字,从而实现组件级局部作用域。
核心机制 / 工作原理
浏览器并不原生理解 .module.css。
CSS Modules 的关键在于构建工具会在编译阶段做几件事:
- 读取模块 CSS 文件。
- 解析其中的类名。
- 为类名生成唯一哈希标识。
- 输出一份类名映射对象给 JavaScript / TypeScript 使用。
例如你写:
.title {
color: red;
}
构建后可能变成:
.Article_title__3f9a2 {
color: red;
}
同时在组件里拿到映射:
{
title: "Article_title__3f9a2"
}
这意味着两个组件都可以写 .title,但最终生成的类名不同,因此不会互相污染。
最小例子 / 最小场景
/* Button.module.css */
.root {
padding: 8px 16px;
border-radius: 6px;
}
.primary {
background: #1677ff;
color: white;
}
import styles from './Button.module.css';
export function Button({ primary }) {
return (
<button className={`${styles.root} ${primary ? styles.primary : ''}`}>
Click
</button>
);
}
这里的 root 和 primary 在组件外不可直接复用其原始类名,这正是它的隔离边界。
边界与易混淆点
- CSS Modules 解决的是类名冲突,不自动解决样式设计是否合理、组件是否拆得清楚。
- 它仍然是 CSS,不会像 CSS-in-JS 一样天然把状态表达式写进样式定义里。
- 当状态很多时,需要组合多个 class,复杂度会回到组件代码里。
- 它偏向“组件私有样式”,跨组件共享时通常还需要额外的 design tokens、公共变量文件或基础样式层。
- 它和 Sass/SCSS 常一起使用,例如
Button.module.scss,前者解决作用域,后者解决表达能力。 - 它和 Vue
scoped都属于编译期隔离思路,但实现方式不同:- CSS Modules 主要通过唯一类名映射。
- Vue
scoped主要通过给选择器追加唯一属性选择器。