Skip to main content

样式文件管理

样式管理的目标是:避免全局污染 + 提升复用性 + 配合构建工具优化产物

主流方案对比

方案作用适用
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,最终产物极小

适合:中后台、组件库、新项目。

五、避坑指南

  1. 不要混用方案:一套项目只用一种(Module 或 Tailwind),否则维护混乱
  2. 避免深层选择器.a .b .c .d 这种嵌套难覆盖,性能也差
  3. 禁用 * 选择器:性能开销大
  4. 样式不要写业务逻辑:颜色、间距走变量,便于主题切换
  5. 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。