CSS-in-JS vs 传统CSS:现代样式方案选择指南

日志切割师
2025-12-18 21:11
阅读 1284

一位文科生转码者的实战思考

大家好,我是一个从中文系自学转行做前端开发的“非典型程序员”。当初刚学 React 的时候,最让我困惑的不是组件怎么写,而是——样式到底该怎么加?

那时候我在网上看到一堆术语:styled-componentsemotionCSS 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(推荐的传统方案)

  1. 创建 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;
}
  1. 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)

  1. 安装后直接在 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 才恍然大悟:“原来可以这么写!”


六、学习建议 & 下一步路径

🚶‍♂️ 新手路线图

  1. 掌握基础 CSS:盒模型、Flex、响应式等(这是地基!)
  2. 学会 CSS Modules:理解“局部作用域”概念
  3. 尝试 styled-components:写几个组件感受动态样式
  4. 了解 Tailwind CSS:另一种现代方案(原子化 CSS)
  5. 结合真实项目:比如用 React + Springboot 做一个 Todo 应用,前后端联调

⚠️ 避坑指南

  • 不要过早追求“最新技术”:先把 CSS 基础打牢,否则 CSS-in-JS 你也写不好。
  • 不要全盘否定传统 CSS:很多场景(如全局主题、动画)传统 CSS 更合适。
  • 命名要有意义:即使是 CSS-in-JS,变量名也要清晰,比如 PrimaryButtonBtn1 好十倍。

结语:你的“代码人生”,从选择开始

从文科生到前端工程师,我深知初学者面对技术选型的迷茫。CSS-in-JS 不是银弹,传统 CSS 也远未过时。关键在于理解场景,做出合适的选择。

在 React 主导的现代前端开发中,CSS-in-JS 提供了更紧密的“逻辑-样式”耦合,极大提升了组件化开发的体验。但如果你正在维护老项目,或者团队偏好传统方式,CSS Modules 依然是稳健之选。

希望这篇指南能帮你少走弯路。记住:工具服务于人,而不是人迁就工具。

你的代码人生,才刚刚开始。写下去,就有答案。


作者:一个仍在写 CSS 的前中文系学生。欢迎在评论区交流你的样式方案选择故事!

评论 0

最热最新
暂无评论
日志切割师Lv.1
0
影响力
0
文章
0
粉丝