CSS-in-JS vs 传统CSS:现代样式方案选择指南
作者说:我当初学前端的时候,光是搞懂“为什么有那么多写样式的办法”就花了好几天。培训班老师讲得很快,一会儿
class,一会儿styled-components,我完全懵了。后来在做实际项目(包括和 Springboot 后端联调)时才真正理解不同方案的优劣。今天,我就以一个“过来人”的身份,用最通俗的语言、最真实的代码,带你一步步搞清楚:到底该用哪种方式写 CSS?
一、什么是 CSS-in-JS?它和传统 CSS 有什么区别?
1.1 传统 CSS 是什么?
传统 CSS 就是我们最熟悉的 .css 文件。你写 HTML,然后在 <head> 里引入一个 .css 文件,通过 class 或 id 来给元素加样式。
<!-- index.html -->
<div class="header">欢迎来到我的网站</div>
/* style.css */
.header {
color: blue;
font-size: 24px;
}
优点:简单、直观、浏览器原生支持。
缺点:全局作用域——如果你在多个页面都用了 .header,很容易样式冲突!
1.2 那 CSS-in-JS 又是什么?
CSS-in-JS 是一种把 CSS 写在 JavaScript 里的技术。比如:
// React 组件中
const Header = styled.div`
color: blue;
font-size: 24px;
`;
它不是真的“不用 CSS”,而是用 JS 动态生成唯一的 class 名,避免冲突。常见库有:
styled-componentsEmotionLinaria(编译时方案)
✅ 核心区别一句话总结:
传统 CSS 是“先写样式,再挂到 HTML 上”;
CSS-in-JS 是“在组件里直接定义样式,自动绑定”。
二、环境准备:搭建一个可运行的项目
我们用一个最小化的 React 项目来演示两种方案。即使你没接触过 React,也不用怕——我会解释每一步。
2.1 安装 Node.js 和 npm
- 去 https://nodejs.org 下载 LTS 版本(推荐 18.x 或 20.x)
- 安装后,在终端运行:
node -v # 应该输出版本号,如 v18.17.0 npm -v # 如 9.6.7
2.2 创建 React 项目
使用官方脚手架 create-react-app(简称 CRA):
npx create-react-app css-compare-demo
cd css-compare-demo
npm start
浏览器会自动打开 http://localhost:3000,看到 React 默认页面就算成功!
💡 新手提示:如果
npx报错,可能是网络问题。可以先运行npm install -g create-react-app,再用create-react-app css-compare-demo。
2.3 安装 CSS-in-JS 库(以 styled-components 为例)
npm install styled-components
2.4 (可选)连接 Springboot 后端?
你可能会问:“文章提到了 Springboot,需要后端吗?”
不需要! 本教程聚焦前端样式。但如果你以后要做全栈项目(比如用 Springboot 提供 API),前端样式方案的选择依然适用。我们只是用这个关键词说明:无论后端是什么,前端样式方案独立存在。
三、核心概念对比:用表格说清楚
| 对比维度 | 传统 CSS | CSS-in-JS(styled-components) |
|---|---|---|
| 作用域 | 全局(容易冲突) | 局部(每个组件样式隔离) |
| 动态样式 | 需要 JS 操作 class 或内联 style | 直接传 props 控制样式 |
| 代码组织 | 样式和逻辑分离 | 样式紧贴组件,高内聚 |
| 性能 | 原生,无额外开销 | 运行时生成 class,略慢(但可忽略) |
| 学习成本 | 极低 | 需要理解 JS 模板字符串、组件概念 |
| 适用场景 | 静态页面、小型项目 | 复杂交互、大型 React/Vue 项目 |
🌰 举个动态样式的例子:
想根据用户登录状态改变按钮颜色。
传统 CSS 方案:
// Button.jsx
function Button({ isLoggedIn }) {
return (
<button className={isLoggedIn ? 'btn-success' : 'btn-default'}>
点击
</button>
);
}
/* style.css */
.btn-success { background: green; }
.btn-default { background: gray; }
CSS-in-JS 方案:
// Button.jsx
import styled from 'styled-components';
const StyledButton = styled.button`
background: ${props => props.isLoggedIn ? 'green' : 'gray'};
`;
function Button({ isLoggedIn }) {
return <StyledButton isLoggedIn={isLoggedIn}>点击</StyledButton>;
}
哪个更直观?对新手来说,传统 CSS 更熟悉;但对复杂逻辑,CSS-in-JS 更简洁。
四、实战项目:做一个主题切换的卡片组件
我们将用两种方式实现同一个功能:一个卡片,可以切换亮色/暗色主题。
4.1 项目结构
src/
├── components/
│ ├── CardTraditional.jsx ← 传统 CSS 实现
│ └── CardStyled.jsx ← CSS-in-JS 实现
├── styles/
│ └── card.css ← 传统 CSS 文件
└── App.jsx
4.2 传统 CSS 实现
第一步:写 CSS 文件
/* src/styles/card.css */
.card-light {
background: white;
color: black;
border: 1px solid #ccc;
padding: 16px;
border-radius: 8px;
}
.card-dark {
background: #333;
color: white;
border: 1px solid #555;
padding: 16px;
border-radius: 8px;
}
第二步:创建组件
// src/components/CardTraditional.jsx
import '../styles/card.css';
export default function CardTraditional({ isDark }) {
const className = isDark ? 'card-dark' : 'card-light';
return (
<div className={className}>
这是一个卡片(传统 CSS)
</div>
);
}
4.3 CSS-in-JS 实现
直接在一个文件里完成:
// src/components/CardStyled.jsx
import styled from 'styled-components';
const StyledCard = styled.div`
background: ${props => props.isDark ? '#333' : 'white'};
color: ${props => props.isDark ? 'white' : 'black'};
border: 1px solid ${props => props.isDark ? '#555' : '#ccc'};
padding: 16px;
border-radius: 8px;
`;
export default function CardStyled({ isDark }) {
return (
<StyledCard isDark={isDark}>
这是一个卡片(CSS-in-JS)
</StyledCard>
);
}
4.4 在 App.jsx 中测试
// src/App.jsx
import { useState } from 'react';
import CardTraditional from './components/CardTraditional';
import CardStyled from './components/CardStyled';
function App() {
const [darkMode, setDarkMode] = useState(false);
return (
<div style={{ padding: '20px' }}>
<button onClick={() => setDarkMode(!darkMode)}>
切换主题 ({darkMode ? '暗' : '亮'})
</button>
<h2>传统 CSS</h2>
<CardTraditional isDark={darkMode} />
<h2>CSS-in-JS</h2>
<CardStyled isDark={darkMode} />
</div>
);
}
export default App;
4.5 运行效果
点击按钮,两个卡片都会同步变色。但你会发现:
- 传统 CSS 需要维护外部
.css文件 - CSS-in-JS 所有逻辑都在一个
.jsx文件里,修改更集中
🔍 打开浏览器开发者工具:
你会发现 CSS-in-JS 生成的 class 名像sc-hKgILt kqXxQY—— 这就是它避免冲突的秘密!
五、新手常见问题解答
❓ Q1:CSS-in-JS 会不会让项目变慢?
答:现代库(如 Emotion、styled-components)经过高度优化,性能损耗微乎其微。除非你渲染上万个动态组件,否则不用担心。
❓ Q2:我该从哪种开始学?
答:先掌握传统 CSS!这是前端基础。等你熟悉 React 组件、props、state 后,再尝试 CSS-in-JS。不要一上来就追求“高级”。
❓ Q3:CSS Modules 算哪种?
答:CSS Modules 是传统 CSS 的“作用域增强版”。它通过编译把 .header 变成 .header_abc123,实现局部作用域。算是中间方案,也值得了解。
❓ Q4:GitHub 上有现成项目可以参考吗?
答:当然!推荐两个资源:
- styled-components 官方示例
- React + Springboot 全栈模板(注意:前端样式部分可替换)
💡 搜索技巧:在 GitHub 搜索
react css-in-js example或react springboot frontend,能找到大量实战项目。
六、学习建议与避坑指南
🧭 学习路径建议
- 第一阶段:熟练使用传统 CSS + HTML。能独立写静态页面。
- 第二阶段:学习 React/Vue 基础,理解组件化思想。
- 第三阶段:尝试 CSS Modules(CRA 已内置支持)。
- 第四阶段:再接触 styled-components 或 Emotion。
⚠️ 新手常踩的坑
- 坑1:在 CSS-in-JS 里写太多逻辑,导致样式文件臃肿
→ 解决:保持样式简单,复杂逻辑抽到 JS 函数里 - 坑2:以为 CSS-in-JS 能完全替代 CSS
→ 事实:全局样式(如 reset.css)仍需传统 CSS - 坑3:不看文档直接复制代码
→ 建议:先读 styled-components 官网入门
📚 推荐资源
- 书籍:《CSS 权威指南》(传统 CSS 必读)
- 视频:B站搜索 “styled-components 零基础”
- 工具:VSCode 插件 “vscode-styled-components”(语法高亮)
结语:没有最好,只有最合适
我当初在培训班做毕业项目时,团队争论了很久用哪种方案。最后我们决定:简单页面用传统 CSS,复杂交互组件用 CSS-in-JS。这种混合策略至今仍在很多大厂使用。
记住:技术是为业务服务的。不要为了用新技术而用新技术。当你能根据项目规模、团队习惯、维护成本做出合理选择时,你就真正“出师”了。
最后送大家一句话:“CSS 不难,难的是理解需求;JS 不难,难的是理清逻辑。”
保持练习,多看 GitHub 开源项目,你会越来越强!
本文所有代码已整理至 GitHub 仓库:
👉 https://github.com/yourname/css-vs-css-in-js-demo
(请将 yourname 替换为你的实际用户名,或搜索类似关键词获取公开示例)
祝你 coding happy!

评论 0