CSS-in-JS 和传统 CSS 到底该怎么选?React 新手必看样式方案指南

VSCode信徒
2026-01-30 20:17
阅读 574

大家好,我是小林,一个在大厂干了3年前端开发的工程师,平时也在B站做技术UP主(欢迎关注!)。最近收到不少粉丝私信问我:“我刚开始学 React,写样式到底该用普通的 CSS 还是 CSS-in-JS 啊?”这个问题其实也是很多前端面试题的高频考点。

我当初学 React 的时候也特别纠结——看到 GitHub 上有的项目用 styled-components,有的用 .module.css,还有的直接写 <style> 标签,简直一头雾水。今天这篇教程,就带零基础的你彻底搞懂 CSS-in-JS传统 CSS 的区别、适用场景,以及如何选择。


一、先搞清楚:什么是“样式方案”?

在前端开发中,样式方案就是指“你怎么给网页元素加颜色、大小、位置这些视觉效果”。

  • 传统 CSS:就是我们最熟悉的 .css 文件,用 <link> 引入 HTML。
  • CSS-in-JS:把 CSS 写在 JavaScript 代码里,通常是用第三方库(比如 styled-components)来实现。

💡 举个生活化的例子:

  • 传统 CSS 像是“先做好菜谱(CSS文件),再按菜谱炒菜(HTML)”
  • CSS-in-JS 像是“边炒菜边写菜谱(样式和逻辑写在一起)”

二、环境准备:5分钟搭建 React 开发环境

我们要用 Vite 创建一个最简 React 项目(比 Create React App 快得多!):

# 1. 打开终端(Mac用Terminal,Win用PowerShell或CMD)
npm create vite@latest my-css-project -- --template react

# 2. 进入项目文件夹
cd my-css-project

# 3. 安装依赖
npm install

# 4. 启动开发服务器
npm run dev

打开浏览器访问 http://localhost:5173,看到 React 的欢迎页面就说明成功了!

✅ 小贴士:如果你还没装 Node.js,请先去 nodejs.org 下载 LTS 版本。


三、核心概念对比:传统 CSS vs CSS-in-JS

1. 传统 CSS(经典三件套)

这是最基础的方式,适合初学者理解样式机制。

// App.jsx
import './App.css';

function App() {
  return <div className="card">Hello World</div>;
}
/* App.css */
.card {
  background: #f0f0f0;
  padding: 16px;
  border-radius: 8px;
}

优点

  • 简单直观,学习成本低
  • 浏览器原生支持,性能好
  • 可以复用样式(比如多个组件用同一个 .btn 类)

缺点

  • 全局作用域 → 容易样式冲突(比如两个组件都写了 .title
  • 无法动态传参(比如根据 props 改变颜色)

2. CSS Modules(传统 CSS 的升级版)

为了解决“全局污染”问题,React 社区推出了 CSS Modules

// App.jsx
import styles from './App.module.css';

function App() {
  return <div className={styles.card}>Hello World</div>;
}
/* App.module.css */
.card {
  background: #f0f0f0;
  padding: 16px;
  border-radius: 8px;
}

注意文件名必须带 .module.css

Vite/React 会自动把 .card 编译成类似 App_card__abc123 的唯一类名,避免冲突。

优点

  • 保留 CSS 语法,学习平滑
  • 自动局部作用域,不怕命名冲突
  • 支持组合(composes)等高级特性

缺点

  • 不能直接使用 JavaScript 变量(比如 props.color

3. CSS-in-JS(把样式写进 JS 里)

最流行的方案是 styled-components,我们来安装它:

npm install styled-components

然后这样写:

// App.jsx
import styled from 'styled-components';

const Card = styled.div`
  background: #f0f0f0;
  padding: 16px;
  border-radius: 8px;
`;

function App() {
  return <Card>Hello World</Card>;
}

更酷的是,它支持动态传参

const Button = styled.button`
  background: ${props => props.primary ? 'blue' : 'gray'};
  color: white;
  padding: 8px 16px;
`;

// 使用
<Button primary>主要按钮</Button>
<Button>普通按钮</Button>

优点

  • 样式与组件强绑定,天然局部作用域
  • 支持 JavaScript 表达式,动态样式超方便
  • 无需管理类名,代码更简洁

缺点

  • 需要额外学习库的语法
  • 运行时有轻微性能开销(但现代浏览器基本无感)
  • 不利于非开发者(如设计师)直接修改样式

四、实战:用三种方式写一个“用户卡片”组件

我们来做一个简单的用户信息卡片,包含头像、姓名、状态(在线/离线)。

方式1:传统 CSS

// UserCard.jsx
import './UserCard.css';

export default function UserCard({ name, status }) {
  return (
    <div className="user-card">
      <img src="/avatar.png" alt="avatar" className="avatar" />
      <div className="info">
        <h3>{name}</h3>
        <span className={`status ${status === 'online' ? 'online' : 'offline'}`}>
          {status}
        </span>
      </div>
    </div>
  );
}
/* UserCard.css */
.user-card {
  display: flex;
  align-items: center;
  padding: 12px;
  border: 1px solid #ddd;
  border-radius: 8px;
}

.avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  margin-right: 12px;
}

.status.online { color: green; }
.status.offline { color: red; }

方式2:CSS Modules

// UserCard.jsx
import styles from './UserCard.module.css';

export default function UserCard({ name, status }) {
  return (
    <div className={styles.userCard}>
      <img src="/avatar.png" alt="avatar" className={styles.avatar} />
      <div className={styles.info}>
        <h3>{name}</h3>
        <span className={`${styles.status} ${styles[status]}`}>
          {status}
        </span>
      </div>
    </div>
  );
}
/* UserCard.module.css */
.userCard {
  display: flex;
  align-items: center;
  padding: 12px;
  border: 1px solid #ddd;
  border-radius: 8px;
}

.avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  margin-right: 12px;
}

.status.online { color: green; }
.status.offline { color: red; }

方式3:CSS-in-JS(styled-components)

// UserCard.jsx
import styled from 'styled-components';

const Card = styled.div`
  display: flex;
  align-items: center;
  padding: 12px;
  border: 1px solid #ddd;
  border-radius: 8px;
`;

const Avatar = styled.img`
  width: 40px;
  height: 40px;
  border-radius: 50%;
  margin-right: 12px;
`;

const Status = styled.span`
  color: ${props => props.status === 'online' ? 'green' : 'red'};
`;

export default function UserCard({ name, status }) {
  return (
    <Card>
      <Avatar src="/avatar.png" alt="avatar" />
      <div>
        <h3>{name}</h3>
        <Status status={status}>{status}</Status>
      </div>
    </Card>
  );
}

🔍 对比一下:

  • 传统 CSS:需要手动管理类名,容易冲突
  • CSS Modules:类名自动隔离,但动态样式写法别扭
  • CSS-in-JS:逻辑和样式高度融合,动态样式一目了然

五、新手常见问题解答

Q1:我该选哪种方案?

场景 推荐方案
学习阶段 / 小型项目 传统 CSS 或 CSS Modules
中大型 React 项目 CSS Modules(主流)或 CSS-in-JS
需要大量动态主题/样式 CSS-in-JS(如 styled-components)
团队有设计师参与 传统 CSS(设计师更熟悉)

Q2:CSS-in-JS 会影响性能吗?

现代方案(如 styled-components v6+)已经做了大量优化,在 99% 的业务场景中性能差异可以忽略。除非你渲染上万个动态组件,否则不用焦虑。

Q3:GitHub 上为什么有人用 Emotion,有人用 styled-components?

它们都是 CSS-in-JS 库,功能类似。styled-components 语法更贴近 CSS,适合新手;Emotion 更轻量,支持 SSR 更好。初学者选 styled-components 即可

Q4:面试官问“CSS-in-JS 优缺点”,怎么答?

✅ 标准回答模板: “CSS-in-JS 的核心优势是样式作用域隔离动态样式支持,特别适合组件化开发。缺点是增加了运行时依赖,且对非 JS 开发者不够友好。在我们团队,对于需要主题切换的后台系统,我们会选用 styled-components;而对于静态展示型页面,优先使用 CSS Modules 保证性能和可维护性。”


六、避坑指南 & 学习建议

⚠️ 新手常犯的错误

  1. 在 CSS-in-JS 里写太多逻辑
    ❌ 错误:background: ${props => props.theme === 'dark' ? (props.disabled ? '#333' : '#000') : ...}
    ✅ 正确:把复杂逻辑抽成函数,保持样式简洁

  2. 滥用 !important
    无论是哪种方案,都尽量避免 !important,它会破坏样式优先级体系。

  3. 不抽离通用样式
    比如按钮、输入框等,应该做成共享组件,而不是每个地方重复写。


📚 下一步学习路径

  1. 先掌握 CSS Modules
    这是目前 React 项目中最主流的方案,GitHub 上大多数开源项目都用它。

  2. 再尝试 styled-components
    做一个小项目(比如 TodoList),体验动态样式的便利。

  3. 了解 Tailwind CSS(可选)
    这是另一种流行方案(原子化 CSS),和 CSS-in-JS 是不同思路,值得了解。

  4. 深入学习 CSS 本身
    无论用什么方案,扎实的 CSS 基础才是根本!推荐 MDN 的 CSS 教程。


七、总结:没有银弹,只有合适

  • 传统 CSS:适合初学者打基础,简单项目够用
  • CSS Modules:React 项目默认推荐,平衡了隔离性和性能
  • CSS-in-JS:适合复杂交互、动态主题,但需权衡学习成本

我在大厂的真实经验:80% 的内部项目用 CSS Modules,20% 高度定制化的产品用 styled-components。你不需要“站队”,而是根据项目需求灵活选择。

最后,别忘了去 GitHub 上看看真实项目是怎么写的!比如:

动手实践才是最好的老师。现在就打开你的编辑器,试试这三种写法吧!

如果觉得这篇教程有帮助,欢迎在评论区留言,或者去 B站 搜索“小林前端”关注我,我会持续更新零基础友好的实战教程!

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝