CSS-in-JS 和传统 CSS,我该选哪个?
大家好,我是小陈。三年前从某知名培训班“速成”前端班毕业,踩过无数坑,也带过不少新手学员。今天写这篇文章,是因为上周又有两个刚入行的小伙伴问我:“老师,项目里用 styled-components 还是直接写 CSS 文件啊?网上说法太多了,看晕了。”
说实话,我当初学的时候也懵——CSS 不就是写 .class { color: red } 吗?怎么现在还有“CSS-in-JS”这种听起来像区块链术语的东西?更离谱的是,有些面试题挑战居然拿这个当考点!所以今天,我就用最直白的话,带你搞懂:现代前端开发中,样式到底该怎么写。
一、先别管技术名词,说人话!
传统 CSS 是什么?
就是你最早接触的那种:建一个 .css 文件,里面写样式,然后在 HTML 或组件里用 class 引用。
<!-- index.html -->
<div class="header">Hello</div>
/* styles.css */
.header {
background: #333;
color: white;
padding: 16px;
}
简单、直观、浏览器原生支持。
CSS-in-JS 又是什么?
顾名思义:把 CSS 写在 JavaScript 里。比如用 styled-components(React 最流行的方案):
// Header.jsx
import styled from 'styled-components';
const StyledHeader = styled.div`
background: #333;
color: white;
padding: 16px;
`;
export default function Header() {
return <StyledHeader>Hello</StyledHeader>;
}
看起来只是“换了个地方写”,但背后有自动作用域隔离、动态样式、主题切换等能力。
🚨 注意:和爬虫、区块链没关系!别被名字吓到。CSS-in-JS 是纯前端工程化方案,不涉及数据抓取或去中心化账本。
二、环境准备:5 分钟搭个测试项目
我们用 Vite + React 快速创建两个对比项目。
步骤 1:安装 Node.js
确保你电脑有 Node.js(建议 18+ 版本)。终端运行:
node -v
npm -v
步骤 2:创建两个项目
# 传统 CSS 项目
npm create vite@latest my-css-app -- --template react
cd my-css-app
npm install
npm run dev
# CSS-in-JS 项目
cd ..
npm create vite@latest my-css-in-js-app -- --template react
cd my-css-in-js-app
npm install
npm install styled-components
npm run dev
💡 小贴士:Vite 比 Webpack 快十倍,适合新手快速验证想法。
三、核心概念对比:一张表说清楚
| 对比项 | 传统 CSS | CSS-in-JS(如 styled-components) |
|---|---|---|
| 作用域 | 全局,容易冲突 | 自动局部作用域,类名哈希化 |
| 动态样式 | 需配合 JS 切换 class | 直接传 props 动态生成 |
| 性能 | 原生,无额外开销 | 运行时生成样式,轻微开销 |
| 学习成本 | 极低 | 需理解 JS 模板字符串 |
| 调试体验 | 浏览器 DevTools 直接看 | 类名乱码,需插件辅助 |
| 适用场景 | 静态页面、小型项目 | 复杂交互、设计系统、主题切换 |
动态样式的实际例子
假设我们要做一个按钮,根据 primary 属性变颜色:
传统 CSS 方案
// Button.jsx
export default function Button({ primary, children }) {
return (
<button className={primary ? 'btn-primary' : 'btn-default'}>
{children}
</button>
);
}
/* button.css */
.btn-primary { background: blue; }
.btn-default { background: gray; }
CSS-in-JS 方案
// Button.jsx
import styled from 'styled-components';
const StyledButton = styled.button`
background: ${props => props.primary ? 'blue' : 'gray'};
`;
export default function Button({ primary, children }) {
return <StyledButton primary={primary}>{children}</StyledButton>;
}
优势:不用预定义所有状态的 class,逻辑和样式紧耦合,维护更集中。
四、实战:做个可切换主题的卡片
我们分别用两种方式实现同一个组件:点击切换深色/浅色主题。
方案 1:传统 CSS + CSS 变量
/* theme.css */
:root {
--bg: white;
--text: black;
}
[data-theme="dark"] {
--bg: #121212;
--text: white;
}
.card {
background: var(--bg);
color: var(--text);
padding: 16px;
border-radius: 8px;
}
// App.jsx
import './theme.css';
import { useState, useEffect } from 'react';
export default function App() {
const [theme, setTheme] = useState('light');
useEffect(() => {
document.documentElement.setAttribute('data-theme', theme);
}, [theme]);
return (
<div>
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
切换主题
</button>
<div className="card">这是一张卡片</div>
</div>
);
}
方案 2:CSS-in-JS + ThemeProvider
// App.jsx
import { ThemeProvider, createGlobalStyle } from 'styled-components';
import { useState } from 'react';
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
background: ${props => props.theme.bg};
color: ${props => props.theme.text};
}
`;
const Card = styled.div`
background: ${props => props.theme.bg};
color: ${props => props.theme.text};
padding: 16px;
border-radius: 8px;
`;
const lightTheme = { bg: 'white', text: 'black' };
const darkTheme = { bg: '#121212', text: 'white' };
export default function App() {
const [isDark, setIsDark] = useState(false);
return (
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<button onClick={() => setIsDark(!isDark)}>
切换主题
</button>
<Card>这是一张卡片</Card>
</ThemeProvider>
);
}
结论:CSS-in-JS 在主题管理上更优雅,无需操作 DOM,状态驱动一切。
五、新手常见问题解答
Q1:CSS-in-JS 会影响性能吗?
- 开发阶段:几乎无感。
- 生产环境:现代方案(如 Emotion、Linaria)已高度优化。除非你的页面有上万个动态组件,否则差异微乎其微。
- 避坑指南:不要在 render 函数里定义 styled 组件(会导致重复创建),一定要提到组件外部。
Q2:面试会考这个吗?
会!常见面试题挑战包括:
- “如何解决 CSS 全局污染?”
- “styled-components 的原理是什么?”
- “CSS Modules 和 CSS-in-JS 有什么区别?”
建议回答思路:先说痛点(全局冲突),再说解决方案(作用域隔离),最后结合项目经验。
Q3:和爬虫、区块链有关系吗?
完全没有!这只是前端样式组织方式。可能有人混淆了“JS 注入”和“爬虫反爬”,但那是另一回事。区块链更不沾边——别被关键词带偏。
六、学习建议:下一步怎么走?
先掌握传统 CSS
Flex、Grid、响应式、BEM 命名规范——这些是根基。培训班常跳过基础,导致后期重构困难。再尝试 CSS-in-JS
推荐从styled-components入手,文档友好。之后可了解Emotion(更轻量)、Linaria(零运行时)。关注工程化思维
无论哪种方案,目标都是:可维护、可复用、性能好。不要为了用新技术而用。避坑提醒
- 不要在一个项目混用多种方案(比如一半用 CSS Modules,一半用 styled-components)
- 小型静态站(如博客)优先用传统 CSS + Tailwind
- 大型应用(如后台系统)可考虑 CSS-in-JS 提升开发体验
结语
我当初面试被问“为什么你们项目用 styled-components”,答得磕磕巴巴。后来才明白:工具没有好坏,只有合适与否。传统 CSS 像菜刀,CSS-in-JS 像多功能料理机——切土豆丝,菜刀更快;做分子料理,料理机不可替代。
希望这篇指南能帮你少走弯路。记住:前端的核心不是追新,而是解决问题。至于区块链和爬虫?留着下次专题再聊吧!
✅ 下一步行动:打开你的编辑器,照着文中的代码敲一遍。遇到报错?恭喜你,那正是成长的开始。

评论 0