一个文科生的样式方案选择指南:CSS-in-JS 和传统 CSS 到底怎么选?
大家好,我是一个从中文系转行做前端的开发者。当初学 CSS 的时候,我以为只要会写 .button { color: red; } 就够了,结果后来发现前端世界远比我想的复杂。尤其是当我开始接触 React、Vue 这些现代框架时,突然冒出来一堆“CSS-in-JS”、“styled-components”、“emotion”这些词,让我一度怀疑自己是不是漏看了什么教材。
今天我就用自己踩过的坑,带大家搞清楚:CSS-in-JS 和传统 CSS 到底有什么区别?什么时候该用哪种?
一、先说说“样式”到底是什么
在网页开发中,“样式”就是控制页面长什么样的部分——比如按钮是红色还是蓝色,文字是居中还是靠左,间距多大等等。传统的做法是用一个 .css 文件来写样式,然后在 HTML 里通过 class 引用。
但随着项目变大,尤其是用了 React 这种组件化框架后,传统 CSS 的一些问题就暴露出来了:
- 全局污染:你写了个
.title,别人也写了个.title,结果互相覆盖。 - 命名困难:为了不冲突,不得不写
.user-profile-header-title这种超长名字。 - 难以复用:想把一个组件的样式完整搬走?光复制 CSS 可能不够,还得检查依赖。
于是,CSS-in-JS 应运而生——它把样式直接写在 JavaScript 里,和组件绑定在一起。
二、环境准备:快速搭建一个 React 项目
我们用 React 作为例子(因为 CSS-in-JS 在 React 生态最流行)。如果你还没装 Node.js,请先去 nodejs.org 下载安装 LTS 版本。
然后打开终端,执行以下命令:
# 创建一个新项目(使用 Vite,速度更快)
npm create vite@latest my-style-project -- --template react
cd my-style-project
npm install
接下来,我们需要安装两个常用的 CSS-in-JS 库:
# 安装 styled-components(最流行的 CSS-in-JS 库)
npm install styled-components
# 如果你想对比传统 CSS,这个项目已经支持 .css 文件了
启动项目:
npm run dev
浏览器打开 http://localhost:5173,看到 “Vite + React” 页面就说明成功了!
三、核心概念:传统 CSS vs CSS-in-JS
1. 传统 CSS 是怎么工作的?
传统方式就是:HTML + CSS 分离。
// App.jsx
import './App.css';
function App() {
return <div className="card">Hello World</div>;
}
/* App.css */
.card {
padding: 16px;
background: #f0f0f0;
border-radius: 8px;
}
✅ 优点:
- 简单直观,所有前端都懂
- 浏览器原生支持,性能好
- 调试方便(开发者工具直接看样式)
❌ 缺点:
- 样式是全局的,容易冲突
- 无法动态传参(比如根据 props 改颜色)
- 组件拆分时样式容易丢失
2. CSS-in-JS 是怎么工作的?
CSS-in-JS 把样式写在 JavaScript 里,通常是用模板字符串的方式。
// App.jsx
import styled from 'styled-components';
const Card = styled.div`
padding: 16px;
background: #f0f0f0;
border-radius: 8px;
`;
function App() {
return <Card>Hello World</Card>;
}
注意:这里 <Card> 不是 HTML 标签,而是一个自定义的 React 组件,它内部已经绑定了样式。
✅ 优点:
- 作用域隔离:每个组件的样式不会影响别人
- 动态样式:可以根据 props 动态改变样式
- 组件即样式:样式和逻辑在一起,迁移更方便
❌ 缺点:
- 需要额外学习库(如 styled-components)
- 运行时有轻微性能开销(但现代浏览器基本无感)
- 对后端开发者不友好(他们可能只熟悉传统 CSS)
📌 我当初学的时候以为 CSS-in-JS 是“取代” CSS,其实不是!它只是另一种组织样式的方式,底层还是生成 CSS。
四、实战项目:做一个可切换主题的卡片
我们来做一个小项目,对比两种方案的写法。
需求:
- 一个卡片组件
- 点击按钮可以切换“浅色”和“深色”主题
- 卡片背景和文字颜色随之变化
方案一:传统 CSS 实现
// CardTraditional.jsx
import './CardTraditional.css';
import { useState } from 'react';
export default function CardTraditional() {
const [isDark, setIsDark] = useState(false);
return (
<div>
<button onClick={() => setIsDark(!isDark)}>
切换到 {isDark ? '浅色' : '深色'}
</button>
<div className={`card ${isDark ? 'dark' : 'light'}`}>
这是一张卡片
</div>
</div>
);
}
/* CardTraditional.css */
.card {
padding: 16px;
border-radius: 8px;
margin-top: 16px;
}
.card.light {
background: #ffffff;
color: #333333;
}
.card.dark {
background: #333333;
color: #ffffff;
}
✅ 优点:清晰,符合直觉
⚠️ 问题:需要手动管理 class 名,如果主题变多,CSS 会越来越臃肿
方案二:CSS-in-JS 实现(styled-components)
// CardStyled.jsx
import styled from 'styled-components';
import { useState } from 'react';
const Card = styled.div`
padding: 16px;
border-radius: 8px;
margin-top: 16px;
background: ${props => props.isDark ? '#333' : '#fff'};
color: ${props => props.isDark ? '#fff' : '#333'};
`;
export default function CardStyled() {
const [isDark, setIsDark] = useState(false);
return (
<div>
<button onClick={() => setIsDark(!isDark)}>
切换到 {isDark ? '浅色' : '深色'}
</button>
<Card isDark={isDark}>
这是一张卡片
</Card>
</div>
);
}
✅ 优点:
- 样式和逻辑完全在一个文件
- 动态值直接通过 props 传递,无需拼接 class
- 不怕命名冲突(每个
Card都是独立的)
💡 技术分享:你会发现,CSS-in-JS 的写法更像“用 JS 写 CSS”,而不是“用 CSS 写样式”。
五、新手常见问题解答
Q1:CSS-in-JS 会不会影响性能?
现代库(如 styled-components、Emotion)都会在构建时做优化,生成唯一的 class 名,并缓存样式。实际性能差距几乎可以忽略,除非你每秒创建上千个动态组件。
Q2:后端同事怎么看 CSS-in-JS?
很多后端开发者习惯传统 CSS,觉得 CSS-in-JS “把简单事情复杂化”。如果你的团队有后端参与前端开发,建议统一风格。纯前端团队可以用 CSS-in-JS,混合团队建议用传统 CSS 或 CSS Modules。
Q3:我该学哪种?
- 如果你做 React 项目,且追求组件化、可维护性 → CSS-in-JS 值得学
- 如果你做 多端项目(比如同时出 Web 和小程序)→ 传统 CSS 更通用
- 如果你刚入门 → 先掌握传统 CSS,再了解 CSS-in-JS
Q4:有没有折中方案?
有!比如 CSS Modules:
/* Card.module.css */
.card {
padding: 16px;
}
import styles from './Card.module.css';
<div className={styles.card}></div>
它能让 CSS 变成局部作用域,又保留了传统 CSS 的写法,是很多团队的“中间路线”。
六、选择建议:一张表帮你决策
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 个人项目 / 快速原型 | CSS-in-JS | 开发快,不用管命名 |
| 大型团队协作 | 传统 CSS + BEM 命名规范 | 后端也能看懂,调试方便 |
| 需要高度动态样式 | CSS-in-JS | 直接用 props 控制样式 |
| 要兼容老项目 | 传统 CSS | 避免引入新依赖 |
| 想学现代前端技术栈 | CSS-in-JS | React 生态主流选择之一 |
七、下一步学习建议
- 先掌握传统 CSS:包括 Flexbox、Grid、响应式设计,这是根基。
- 尝试 CSS Modules:它是传统 CSS 的“安全升级版”。
- 再学 styled-components:官方文档很友好,https://styled-components.com/
- 了解 Tailwind CSS:这是另一种现代方案(原子化 CSS),和 CSS-in-JS 是不同思路。
🚫 避坑指南:不要一上来就钻进 CSS-in-JS,结果连
box-sizing是啥都不知道。工具是为解决问题服务的,不是炫技的。
最后的话
我当初转码时,总想一步到位学会“最先进”的技术。但后来明白:没有最好的方案,只有最适合当前项目的方案。
CSS-in-JS 和传统 CSS 不是对立关系,而是工具箱里的两把锤子。你需要根据钉子的大小、位置、材质,选择合适的那一把。
希望这篇教程能帮你少走弯路。如果你是文科生,也别怕——我都能学会,你一定也可以!
技术分享不易,欢迎点赞、转发给正在纠结样式方案的朋友。下期我们聊聊“如何用 CSS 画一个会动的 loading 动画”!

评论 0