CSS-in-JS vs 传统CSS:现代样式方案选择指南
一位文科生转码者的实战思考
大家好,我是一个从中文系自学转行做前端开发的“非典型程序员”。当初刚学 React 的时候,最让我困惑的不是组件怎么写,而是——样式到底该怎么加?
那时候我在网上看到一堆术语:styled-components、emotion、CSS Modules、还有人说“别用 CSS 了,都用 JS 写样式吧”……我一头雾水。更别提后来工作中还要和后端同学联调 Springboot 接口,前端样式一乱,整个页面就“代码人生”变“混乱人生”了。
所以今天,我想用最通俗的语言,带你搞清楚:CSS-in-JS 和传统 CSS 到底有什么区别?我们该选哪个?
一、什么是 CSS-in-JS?它和传统 CSS 有啥不同?
简单说:
- 传统 CSS:你写一个
.css文件,里面定义.button { color: red; },然后在 HTML 或 JSX 里用className="button"引用。 - CSS-in-JS:你直接在 JavaScript(或 React)代码里写样式,比如用一个函数生成带样式的组件。
我当初学的时候以为 CSS-in-JS 是“不用写 CSS 了”,其实不是!它只是把 CSS 写在 JS 里,底层还是生成 CSS,只是管理方式变了。
核心区别对比表
| 对比维度 | 传统 CSS | CSS-in-JS(如 styled-components) |
|---|---|---|
| 文件位置 | 独立 .css 文件 |
写在 .js / .jsx 文件中 |
| 样式作用域 | 全局(容易冲突) | 自动局部作用域(组件级隔离) |
| 动态样式 | 需要切换 class 或内联 style | 直接传 props 控制样式 |
| 工具链依赖 | 几乎无需额外配置 | 需安装库(如 styled-components) |
| 与 JS 交互 | 较弱 | 极强(可读取 state、props 等) |
二、环境准备:搭建一个 React 小项目
我们用官方脚手架快速创建项目(不需要懂 Springboot,但知道它常作为后端服务就行):
# 创建 React 应用
npx create-react-app css-compare-demo
# 进入目录
cd css-compare-demo
# 安装 styled-components(主流 CSS-in-JS 库)
npm install styled-components
# 启动开发服务器
npm start
💡 提示:如果你公司用的是 Vite 或 Next.js,步骤类似,这里用 CRA 最简单。
三、核心概念:用最直白的话讲清楚
1. 传统 CSS 的痛点
- 全局污染:你在 A 组件写
.title,B 组件也写.title,样式会互相覆盖。 - 命名焦虑:为了不冲突,你不得不写
.user-profile-header-title这种超长类名。 - 动态样式麻烦:想根据状态变颜色?得写多个 class,再用 JS 切换。
2. CSS-in-JS 的优势
- 自动隔离:每个组件的样式只属于它自己,不怕冲突。
- 动态能力强大:直接读取 props,比如
<Button primary={true}>就变蓝色。 - 逻辑与样式共存:样式和组件写在一起,维护更集中。
我当初在做一个后台管理系统时,用传统 CSS 写了 200 行样式,结果两个页面按钮样式串了。换成 styled-components 后,问题直接消失。
四、实战:同一个按钮,两种写法对比
我们来实现一个“可切换主色”的按钮。
方案一:传统 CSS + CSS Modules(推荐的传统方案)
- 创建
Button.module.css:
/* Button.module.css */
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.primary {
background-color: #3b82f6;
color: white;
}
.secondary {
background-color: #e5e7eb;
color: #374151;
}
- 在
Button.js中使用:
import styles from './Button.module.css';
export default function Button({ primary, children }) {
const className = primary
? `${styles.btn} ${styles.primary}`
: `${styles.btn} ${styles.secondary}`;
return <button className={className}>{children}</button>;
}
✅ 优点:保留了 CSS 语法,通过 .module.css 实现局部作用域。
❌ 缺点:动态逻辑仍需拼接字符串,不够直观。
方案二:CSS-in-JS(styled-components)
- 安装后直接在
Button.js写:
import styled from 'styled-components';
const StyledButton = styled.button`
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
background-color: ${props => props.primary ? '#3b82f6' : '#e5e7eb'};
color: ${props => props.primary ? 'white' : '#374151'};
`;
export default function Button({ primary, children }) {
return <StyledButton primary={primary}>{children}</StyledButton>;
}
✅ 优点:样式和逻辑完全融合,一行代码搞定动态颜色。
✅ 更简洁:无需管理 class 名,props 直接驱动样式。
这就是我后来在实战中最爱的方式——尤其在 React 项目里,开发效率提升明显。
五、新手常见问题解答
Q1:CSS-in-JS 会影响性能吗?
早期确实有轻微开销,但现在主流库(如 emotion、styled-components)都做了优化,对绝大多数应用无感。除非你做超高频动画(如游戏),否则不用担心。
Q2:团队有人坚持用传统 CSS,怎么办?
完全可以混合使用!比如:
- 基础布局、重置样式用传统 CSS
- 组件样式用 CSS-in-JS
很多大厂(包括我之前实习的公司)都是这样做的。
Q3:Springboot 后端需要关心前端用哪种样式方案吗?
完全不需要! Springboot 只负责提供 API 接口,前端怎么写样式,后端毫无感知。这也是前后端分离的好处。
Q4:我该从哪种开始学?
- 如果你是纯新手 → 先学传统 CSS + CSS Modules,理解基础概念。
- 如果你已经会 React → 直接上 styled-components,体验现代化开发。
我当初是先啃了两个月原生 CSS,后来接触 CSS-in-JS 才恍然大悟:“原来可以这么写!”
六、学习建议 & 下一步路径
🚶♂️ 新手路线图
- 掌握基础 CSS:盒模型、Flex、响应式等(这是地基!)
- 学会 CSS Modules:理解“局部作用域”概念
- 尝试 styled-components:写几个组件感受动态样式
- 了解 Tailwind CSS:另一种现代方案(原子化 CSS)
- 结合真实项目:比如用 React + Springboot 做一个 Todo 应用,前后端联调
⚠️ 避坑指南
- 不要过早追求“最新技术”:先把 CSS 基础打牢,否则 CSS-in-JS 你也写不好。
- 不要全盘否定传统 CSS:很多场景(如全局主题、动画)传统 CSS 更合适。
- 命名要有意义:即使是 CSS-in-JS,变量名也要清晰,比如
PrimaryButton比Btn1好十倍。
结语:你的“代码人生”,从选择开始
从文科生到前端工程师,我深知初学者面对技术选型的迷茫。CSS-in-JS 不是银弹,传统 CSS 也远未过时。关键在于理解场景,做出合适的选择。
在 React 主导的现代前端开发中,CSS-in-JS 提供了更紧密的“逻辑-样式”耦合,极大提升了组件化开发的体验。但如果你正在维护老项目,或者团队偏好传统方式,CSS Modules 依然是稳健之选。
希望这篇指南能帮你少走弯路。记住:工具服务于人,而不是人迁就工具。
你的代码人生,才刚刚开始。写下去,就有答案。
作者:一个仍在写 CSS 的前中文系学生。欢迎在评论区交流你的样式方案选择故事!

评论 0