在现代前端工程化体系里,样式方案一直是开发者绕不开的话题。从原生 CSS、预处理器(Less/Sass)、CSS Modules,再到如今主流的 CSS-in-JS,样式开发正在从「全局松散」走向「组件强绑定」,从「静态编写」走向「动态可控」。
这篇文章就带你完整理解:CSS-in-JS 是什么、为什么要用、主流库对比、以及真实项目中的最佳实践。
一、什么是 CSS-in-JS?
CSS-in-JS 并不是一种新语法,而是一种模式:在 JavaScript 文件中编写组件样式,让样式与组件逻辑强绑定。
它和 CSS Modules 一样,解决样式全局污染、命名冲突、样式复用混乱等问题,但更进一步:
- 样式直接写在组件内,组件即孤岛
- 天然支持动态样式(根据 props/state 变化)
- 自动作用域隔离,不需要手动管理类名
- 支持主题、变量、嵌套、自动前缀等能力
典型库:
- styled-components(最流行)
- Emotion(性能更好,体积更小)
- Linaria(零运行时 CSS-in-JS)
- JSS / Styled-JSX
二、为什么需要 CSS-in-JS?
1. 彻底告别类名冲突
不再需要 BEM、OOCSS 等复杂命名规范,组件样式天然局部化。
2. 真正的组件级复用
样式和组件一起封装、一起导出、一起复用,比单独抽 CSS 文件更内聚。
3. 动态样式极其方便
根据 props 切换颜色、尺寸、主题,不需要拼接类名,代码更直观。
4. 更好的 Tree-Shaking
无用样式更容易被打包工具剔除,减少冗余 CSS。
5. 主题系统天然友好
适合设计系统、组件库、深色模式等场景。
三、CSS-in-JS 核心优势
- 作用域绝对安全
- 动态样式原生支持
- 组件内聚性极强
- 无需管理类名
- 支持服务端渲染(SSR)友好
- 主题、变量、自动前缀一体化
四、快速上手:styled-components 示例
1. 安装
bash
运行
npm install styled-components
2. 基础使用
jsx
import styled from 'styled-components';
// 创建带样式的组件
const Button = styled.button`
padding: 8px 16px;
border: none;
border-radius: 4px;
background: #1677ff;
color: white;
cursor: pointer;
&:hover {
opacity: 0.9;
}
`;
function App() {
return <Button>CSS-in-JS 按钮</Button>;
}
3. 动态样式(根据 Props)
jsx
const Button = styled.button`
background: ${props => props.primary ? '#1677ff' : '#fff'};
color: ${props => props.primary ? '#fff' : '#333'};
`;
<Button primary>主要按钮</Button>
<Button>次要按钮</Button>
4. 样式扩展
jsx
const PrimaryButton = styled(Button)`
font-weight: bold;
`;
五、CSS-in-JS vs CSS Modules 对比
表格
| 特性 | CSS Modules | CSS-in-JS |
|---|---|---|
| 编写位置 | 单独 CSS 文件 | JS/JSX 内部 |
| 作用域 | 类名哈希 | 类名哈希 + 组件隔离 |
| 动态样式 | 需拼接类名 | 天然支持 |
| 学习成本 | 极低 | 中等 |
| 运行时开销 | 无 | 有(除 Linaria) |
| 组件内聚 | 一般 | 极高 |
| 主题系统 | 弱 | 强 |
简单总结:
- 追求轻量、无 runtime、传统风格 → CSS Modules
- 追求组件化、动态样式、主题系统 → CSS-in-JS
六、CSS-in-JS 缺点与争议
- 运行时性能开销样式需要在浏览器端解析生成,大量动态样式可能卡顿。
- 学习成本略高模板字符串、props 穿透、样式优先级需要适应。
- CSS 语法提示不如原生文件友好需要插件支持。
- SSR 配置稍复杂需处理样式收集与注水。
七、最佳实践建议
- 中小型项目:CSS Modules 足够简单高效
- 中大型项目 / 组件库 / 设计系统:优先 CSS-in-JS
- 追求极致性能:选择 Emotion 或 Linaria(零运行时)
- 避免过度动态:大量 props 判断会影响可读性
- 统一主题:使用 ThemeProvider 管理全局主题
- 不要混用太多方案:避免项目风格混乱
八、总结
CSS-in-JS 是组件化时代的自然演进。它以更强的内聚性、动态能力和工程化友好度,成为现代 React/Vue 生态中非常主流的样式方案,尤其适合复杂交互、主题系统、跨端组件。
如果你已经受够了全局样式污染、类名混乱、动态样式难写,CSS-in-JS 会是体验极佳的升级选择。