CSS-in-JS 和传统 CSS 到底怎么选?前端新人避坑指南
大家好!我是小林,一名 211 高校的计算机专业研究生,平时喜欢写技术博客帮助刚入门的同学少走弯路。最近在辅导几位学弟准备前端求职时,发现他们对“CSS-in-JS”和“传统 CSS”的区别非常困惑——这甚至成了不少大厂的面试题!于是,我决定写这篇零基础教程,用最直白的方式讲清楚:这两种样式方案到底是什么?该怎么选?对求职有没有影响?
我当初学前端时,也在这两个概念里绕了好久。今天,我就手把手带你搞懂它们,还会带你做一个小项目,真正理解它们的差异。
一、什么是 CSS-in-JS?它和传统 CSS 有什么不同?
简单来说:
- 传统 CSS:你写一个
.css文件,用class或id给 HTML 元素加样式。 - CSS-in-JS:你直接在 JavaScript(或 JSX)里写样式,样式代码和组件逻辑写在一起。
听起来有点抽象?别急,我们先看个例子。
传统 CSS 写法(React 中)
// Button.js
import './Button.css';
function Button() {
return <button className="primary-btn">点击我</button>;
}
/* Button.css */
.primary-btn {
background-color: blue;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
}
CSS-in-JS 写法(以 styled-components 为例)
// Button.js
import styled from 'styled-components';
const PrimaryButton = styled.button`
background-color: blue;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
`;
function Button() {
return <PrimaryButton>点击我</PrimaryButton>;
}
看到区别了吗?传统 CSS 是“分离式”,而 CSS-in-JS 是“内联式”(但不是真的内联 style,而是通过 JS 动态生成 CSS)。
二、开发环境准备(5 分钟搞定)
为了动手实践,我们需要搭建一个简单的 React 开发环境。
步骤 1:安装 Node.js
去 https://nodejs.org 下载 LTS 版本并安装。安装后终端输入:
node -v
npm -v
能看到版本号就说明装好了。
步骤 2:创建 React 项目
npx create-react-app css-comparison-demo
cd css-comparison-demo
步骤 3:安装 CSS-in-JS 库(styled-components)
npm install styled-components
💡 提示:styled-components 是目前最流行的 CSS-in-JS 库之一,语法接近原生 CSS,非常适合新手。
步骤 4:启动项目
npm start
浏览器会自动打开 http://localhost:3000,看到 React 默认页面就成功了!
三、核心概念对比:一张表说清楚
| 对比项 | 传统 CSS | CSS-in-JS(如 styled-components) |
|---|---|---|
| 作用域 | 全局(容易冲突) | 自动局部作用域(每个组件独立) |
| 动态样式 | 需要手动切换 class 或用 inline style | 直接传 props 控制样式 |
| 可维护性 | 样式分散,大型项目难管理 | 样式紧贴组件,高内聚 |
| 性能 | 静态文件,加载快 | 运行时生成 CSS,略慢 |
| 学习成本 | 极低,前端必学 | 需理解 JS 和模板字符串 |
| 工程化支持 | 支持预处理器(如 Sass) | 通常不支持,但可嵌入 JS 逻辑 |
关键点解释
1. 作用域问题(最重要!)
传统 CSS 的 class 是全局的。比如你写了 .btn,另一个同事也写了 .btn,就会互相覆盖!
CSS-in-JS 自动生成唯一的 class 名(比如 sc-fzqBZW kLmNop),完全隔离,再也不怕命名冲突。
2. 动态样式超方便
想根据 props 改变按钮颜色?传统做法:
<button className={props.type === 'danger' ? 'btn-danger' : 'btn-primary'}>
然后在 CSS 里定义两个 class。
而 CSS-in-JS 只需:
const Button = styled.button`
background-color: ${props => props.type === 'danger' ? 'red' : 'blue'};
`;
是不是更直观?
四、实战:用两种方式实现一个“主题切换”按钮
我们现在来做一个小功能:点击按钮,切换网站主题(浅色/深色)。分别用传统 CSS 和 CSS-in-JS 实现,感受差异。
方案一:传统 CSS 实现
- 创建
ThemeToggle.css:
.theme-toggle {
padding: 8px 16px;
background: #007bff;
color: white;
border: none;
cursor: pointer;
}
body.dark-theme {
background-color: #121212;
color: #ffffff;
}
body.light-theme {
background-color: #ffffff;
color: #000000;
}
- 在
App.js中:
import './ThemeToggle.css';
import { useState, useEffect } from 'react';
function App() {
const [theme, setTheme] = useState('light');
useEffect(() => {
document.body.className = `${theme}-theme`;
}, [theme]);
return (
<div>
<button
className="theme-toggle"
onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
>
切换到{theme === 'light' ? '深色' : '浅色'}模式
</button>
</div>
);
}
✅ 能跑,但需要操作 document.body,有点“侵入式”。
方案二:CSS-in-JS 实现(styled-components)
- 修改
App.js:
import styled, { createGlobalStyle } from 'styled-components';
import { useState } from 'react';
// 定义全局样式(替代 body 的样式)
const GlobalStyle = createGlobalStyle`
body {
background-color: ${props => props.theme.bg};
color: ${props => props.theme.text};
margin: 0;
font-family: sans-serif;
}
`;
// 主题配置
const themes = {
light: { bg: '#ffffff', text: '#000000' },
dark: { bg: '#121212', text: '#ffffff' }
};
const ToggleButton = styled.button`
padding: 8px 16px;
background: #007bff;
color: white;
border: none;
cursor: pointer;
border-radius: 4px;
`;
function App() {
const [currentTheme, setCurrentTheme] = useState('light');
return (
<>
<GlobalStyle theme={themes[currentTheme]} />
<ToggleButton
onClick={() => setCurrentTheme(prev => prev === 'light' ? 'dark' : 'light')}
>
切换到{currentTheme === 'light' ? '深色' : '浅色'}模式
</ToggleButton>
</>
);
}
✅ 样式完全由 React 状态控制,无需操作 DOM,更符合 React 思维!
五、新手常见问题解答(FAQ)
Q1:CSS-in-JS 会影响性能吗?
答:在绝大多数业务场景中,影响微乎其微。现代 CSS-in-JS 库(如 styled-components v6)已做大量优化。除非是超高性能要求的场景(如游戏、复杂动画),否则不必担心。
Q2:传统 CSS 会被淘汰吗?
答:不会!很多公司(尤其是中后台系统)仍在用传统 CSS + BEM 命名规范。而且 Tailwind CSS 等原子化 CSS 的流行,也让传统 CSS 焕发新生。
Q3:面试官问我“CSS-in-JS 的优缺点”,怎么答?
答:记住这个答题模板:
“CSS-in-JS 的优点是作用域隔离、动态样式灵活、组件化程度高;缺点是增加了 JS bundle 体积、调试时 class 名不直观、不利于非 JS 开发者协作。我们团队在项目中根据复杂度选择:简单页面用传统 CSS,复杂交互组件用 CSS-in-JS。”
这回答既有技术深度,又体现工程思维,加分项!
Q4:我该先学哪个?
答:先掌握传统 CSS!它是前端基石。理解盒模型、定位、Flex/Grid 后,再学 CSS-in-JS 才能体会到它的价值。别一上来就跳进新方案,基础不牢,地动山摇。
六、学习建议与求职准备
📌 学习路径推荐
- 第一阶段(1-2周):扎实掌握传统 CSS(MDN 文档 + Flexbox Froggy 游戏)
- 第二阶段(1周):学习 CSS 模块化(CSS Modules)作为过渡
- 第三阶段(1周):尝试 styled-components 或 Emotion
- 第四阶段:了解 Tailwind CSS、Sass 等其他方案,拓宽视野
🎯 求职准备重点
- 简历上写清楚你用过哪种方案,并说明“为什么选它”
- 准备一道对比题:比如“你们项目为什么不用 CSS-in-JS?”
- 动手能力比理论更重要:面试官可能让你现场写一个带 hover 效果的按钮,用任意方案都行,但要写得干净
⚠️ 避坑指南
- ❌ 不要为了用新技术而用新技术。一个小静态页用 CSS-in-JS 反而是过度设计。
- ✅ 大型 React/Vue 项目,尤其是需要主题切换、动态 UI 的,CSS-in-JS 优势明显。
- 🔁 传统 CSS 并不“老土”,配合 PostCSS、PurgeCSS 等工具,依然非常强大。
结语:没有银弹,只有合适
我当初面试字节时,就被问到这个问题。当时我如实说:“我们在内部工具用传统 CSS,因为简单;但在用户端产品用 styled-components,因为要支持多主题。” 面试官点点头,说:“很好,你知道根据场景做技术选型。”
技术没有绝对好坏,只有是否适合当前场景。
希望这篇教程能帮你理清思路,不再被“CSS-in-JS vs 传统 CSS”困扰。如果你觉得有帮助,欢迎关注我的博客,我会持续更新前端求职和面试题解析!
下一步,你可以尝试:
- 用 CSS Modules 重写上面的例子
- 研究 styled-components 的
ThemeProvider - 读一读《CSS 世界》这本书,夯实基础
加油,前端路上,我们一起进步!

评论 0