样式文件管理
样式管理的目标是:避免全局污染 + 提升复用性 + 配合构建工具优化产物。
主流方案对比
| 方案 | 作用 | 适用 |
|---|---|---|
| CSS 原生 | 简单 BEM 命名 | 极小项目 |
| CSS Module | 自动局部作用域 | 通用推荐 |
| CSS-in-JS(styled-components / emotion) | 组件级样式 | React 组件库 |
| 原子化 CSS(Tailwind / UnoCSS) | 工具类优先 | 现代项目首选 |
| 预处理器(less / sass) | 变量、嵌套、mixin | 配合 Module 使用 |
2024 年起,Tailwind / UnoCSS 越来越主流;传统业务仍然 CSS Module 够用。
一、CSS Module(最通用)
1. 基本使用
// Button.module.less
.btn {
padding: 8px 16px;
background: @primary-color;
border-radius: 4px;
}
.primary {
background: blue;
color: white;
}
import styles from "./Button.module.less";
export const Button = ({ type, children }) => (
<button className={`${styles.btn} ${type === "primary" ? styles.primary : ""}`}>
{children}
</button>
);
构建后会编译成 .btn_x1y2z 这种带 hash 的类名,天然隔离。
2. 配置(webpack)
{
test: /\.module\.less$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: {
localIdentName: "[name]_[local]_[hash:base64:5]",
},
},
},
"less-loader",
],
}
3. 全局 less 变量
pnpm add style-resources-loader -D
// webpack.config.js
{
loader: "style-resources-loader",
options: {
patterns: path.resolve(__dirname, "src/styles/global.less"),
},
}
4. TypeScript 类型声明
// src/global.d.ts
declare module "*.module.less" {
const classes: { readonly [key: string]: string };
export default classes;
}
二、组织方式
方案 A:组件 + 样式同目录
Button/
├─ index.tsx
├─ Button.tsx
└─ Button.module.less
优点:组件内聚,复制即用。
方案 B:独立 styles 目录
src/
├─ components/
│ └─ Button.tsx
└─ styles/
├─ variables.less
├─ mixins.less
└─ components/
└─ Button.less
优点:样式集中管理,适合设计 token 体系。
个人推荐方案 A,维护成本低。
三、全局样式
仅放真正的全局内容:
// global.less
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; font-family: -apple-system, sans-serif; }
:root {
--primary-color: #1890ff;
--text-color: #333;
--bg-color: #fff;
}
推荐用 CSS Variables 配合主题切换,比 less 变量更灵活。
四、原子化 CSS(Tailwind / UnoCSS)
<button className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
Click
</button>
优点:
- 不用想类名
- 天然没有命名冲突
- 配合 PurgeCSS,最终产物极小
适合:中后台、组件库、新项目。
五、避坑指南
- 不要混用方案:一套项目只用一种(Module 或 Tailwind),否则维护混乱
- 避免深层选择器:
.a .b .c .d这种嵌套难覆盖,性能也差 - 禁用
*选择器:性能开销大 - 样式不要写业务逻辑:颜色、间距走变量,便于主题切换
- CSS 动画用 transform / opacity:避免触发布局重排
六、面试高频
- Q:CSS Module 怎么实现局部作用域?
A:构建时给类名加上 hash 后缀(如
.btn_x1y2z),全局唯一,避免冲突。 - Q:CSS-in-JS 的优缺点? A:优点 - 组件级作用域、动态主题、TypeScript 支持;缺点 - runtime 性能损耗、SSR 兼容问题、调试不友好。
- Q:Tailwind 和 CSS Module 怎么选? A:现代项目、原型阶段、组件库 → Tailwind;传统业务、复杂自定义样式、团队学习成本 → CSS Module。