一个文科生的样式方案选择指南:CSS-in-JS 和传统 CSS 到底怎么选?

产品和代码之间
2026-01-28 12:44
阅读 438

大家好,我是一个从中文系转行做前端的开发者。当初学 CSS 的时候,我以为只要会写 .button { color: red; } 就够了,结果后来发现前端世界远比我想的复杂。尤其是当我开始接触 React、Vue 这些现代框架时,突然冒出来一堆“CSS-in-JS”、“styled-components”、“emotion”这些词,让我一度怀疑自己是不是漏看了什么教材。

今天我就用自己踩过的坑,带大家搞清楚:CSS-in-JS 和传统 CSS 到底有什么区别?什么时候该用哪种?


一、先说说“样式”到底是什么

在网页开发中,“样式”就是控制页面长什么样的部分——比如按钮是红色还是蓝色,文字是居中还是靠左,间距多大等等。传统的做法是用一个 .css 文件来写样式,然后在 HTML 里通过 class 引用。

但随着项目变大,尤其是用了 React 这种组件化框架后,传统 CSS 的一些问题就暴露出来了:

  • 全局污染:你写了个 .title,别人也写了个 .title,结果互相覆盖。
  • 命名困难:为了不冲突,不得不写 .user-profile-header-title 这种超长名字。
  • 难以复用:想把一个组件的样式完整搬走?光复制 CSS 可能不够,还得检查依赖。

于是,CSS-in-JS 应运而生——它把样式直接写在 JavaScript 里,和组件绑定在一起。


二、环境准备:快速搭建一个 React 项目

我们用 React 作为例子(因为 CSS-in-JS 在 React 生态最流行)。如果你还没装 Node.js,请先去 nodejs.org 下载安装 LTS 版本。

然后打开终端,执行以下命令:

# 创建一个新项目(使用 Vite,速度更快)
npm create vite@latest my-style-project -- --template react
cd my-style-project
npm install

接下来,我们需要安装两个常用的 CSS-in-JS 库:

# 安装 styled-components(最流行的 CSS-in-JS 库)
npm install styled-components

# 如果你想对比传统 CSS,这个项目已经支持 .css 文件了

启动项目:

npm run dev

浏览器打开 http://localhost:5173,看到 “Vite + React” 页面就说明成功了!


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

1. 传统 CSS 是怎么工作的?

传统方式就是:HTML + CSS 分离

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

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

✅ 优点:

  • 简单直观,所有前端都懂
  • 浏览器原生支持,性能好
  • 调试方便(开发者工具直接看样式)

❌ 缺点:

  • 样式是全局的,容易冲突
  • 无法动态传参(比如根据 props 改颜色)
  • 组件拆分时样式容易丢失

2. CSS-in-JS 是怎么工作的?

CSS-in-JS 把样式写在 JavaScript 里,通常是用模板字符串的方式。

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

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

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

注意:这里 <Card> 不是 HTML 标签,而是一个自定义的 React 组件,它内部已经绑定了样式。

✅ 优点:

  • 作用域隔离:每个组件的样式不会影响别人
  • 动态样式:可以根据 props 动态改变样式
  • 组件即样式:样式和逻辑在一起,迁移更方便

❌ 缺点:

  • 需要额外学习库(如 styled-components)
  • 运行时有轻微性能开销(但现代浏览器基本无感)
  • 对后端开发者不友好(他们可能只熟悉传统 CSS)

📌 我当初学的时候以为 CSS-in-JS 是“取代” CSS,其实不是!它只是另一种组织样式的方式,底层还是生成 CSS。


四、实战项目:做一个可切换主题的卡片

我们来做一个小项目,对比两种方案的写法。

需求:

  • 一个卡片组件
  • 点击按钮可以切换“浅色”和“深色”主题
  • 卡片背景和文字颜色随之变化

方案一:传统 CSS 实现

// CardTraditional.jsx
import './CardTraditional.css';
import { useState } from 'react';

export default function CardTraditional() {
  const [isDark, setIsDark] = useState(false);

  return (
    <div>
      <button onClick={() => setIsDark(!isDark)}>
        切换到 {isDark ? '浅色' : '深色'}
      </button>
      <div className={`card ${isDark ? 'dark' : 'light'}`}>
        这是一张卡片
      </div>
    </div>
  );
}
/* CardTraditional.css */
.card {
  padding: 16px;
  border-radius: 8px;
  margin-top: 16px;
}

.card.light {
  background: #ffffff;
  color: #333333;
}

.card.dark {
  background: #333333;
  color: #ffffff;
}

✅ 优点:清晰,符合直觉
⚠️ 问题:需要手动管理 class 名,如果主题变多,CSS 会越来越臃肿


方案二:CSS-in-JS 实现(styled-components)

// CardStyled.jsx
import styled from 'styled-components';
import { useState } from 'react';

const Card = styled.div`
  padding: 16px;
  border-radius: 8px;
  margin-top: 16px;
  background: ${props => props.isDark ? '#333' : '#fff'};
  color: ${props => props.isDark ? '#fff' : '#333'};
`;

export default function CardStyled() {
  const [isDark, setIsDark] = useState(false);

  return (
    <div>
      <button onClick={() => setIsDark(!isDark)}>
        切换到 {isDark ? '浅色' : '深色'}
      </button>
      <Card isDark={isDark}>
        这是一张卡片
      </Card>
    </div>
  );
}

✅ 优点:

  • 样式和逻辑完全在一个文件
  • 动态值直接通过 props 传递,无需拼接 class
  • 不怕命名冲突(每个 Card 都是独立的)

💡 技术分享:你会发现,CSS-in-JS 的写法更像“用 JS 写 CSS”,而不是“用 CSS 写样式”。


五、新手常见问题解答

Q1:CSS-in-JS 会不会影响性能?

现代库(如 styled-components、Emotion)都会在构建时做优化,生成唯一的 class 名,并缓存样式。实际性能差距几乎可以忽略,除非你每秒创建上千个动态组件。

Q2:后端同事怎么看 CSS-in-JS?

很多后端开发者习惯传统 CSS,觉得 CSS-in-JS “把简单事情复杂化”。如果你的团队有后端参与前端开发,建议统一风格。纯前端团队可以用 CSS-in-JS,混合团队建议用传统 CSS 或 CSS Modules

Q3:我该学哪种?

  • 如果你做 React 项目,且追求组件化、可维护性 → CSS-in-JS 值得学
  • 如果你做 多端项目(比如同时出 Web 和小程序)→ 传统 CSS 更通用
  • 如果你刚入门 → 先掌握传统 CSS,再了解 CSS-in-JS

Q4:有没有折中方案?

有!比如 CSS Modules

/* Card.module.css */
.card {
  padding: 16px;
}
import styles from './Card.module.css';
<div className={styles.card}></div>

它能让 CSS 变成局部作用域,又保留了传统 CSS 的写法,是很多团队的“中间路线”。


六、选择建议:一张表帮你决策

场景 推荐方案 理由
个人项目 / 快速原型 CSS-in-JS 开发快,不用管命名
大型团队协作 传统 CSS + BEM 命名规范 后端也能看懂,调试方便
需要高度动态样式 CSS-in-JS 直接用 props 控制样式
要兼容老项目 传统 CSS 避免引入新依赖
想学现代前端技术栈 CSS-in-JS React 生态主流选择之一

七、下一步学习建议

  1. 先掌握传统 CSS:包括 Flexbox、Grid、响应式设计,这是根基。
  2. 尝试 CSS Modules:它是传统 CSS 的“安全升级版”。
  3. 再学 styled-components:官方文档很友好,https://styled-components.com/
  4. 了解 Tailwind CSS:这是另一种现代方案(原子化 CSS),和 CSS-in-JS 是不同思路。

🚫 避坑指南:不要一上来就钻进 CSS-in-JS,结果连 box-sizing 是啥都不知道。工具是为解决问题服务的,不是炫技的


最后的话

我当初转码时,总想一步到位学会“最先进”的技术。但后来明白:没有最好的方案,只有最适合当前项目的方案

CSS-in-JS 和传统 CSS 不是对立关系,而是工具箱里的两把锤子。你需要根据钉子的大小、位置、材质,选择合适的那一把。

希望这篇教程能帮你少走弯路。如果你是文科生,也别怕——我都能学会,你一定也可以!

技术分享不易,欢迎点赞、转发给正在纠结样式方案的朋友。下期我们聊聊“如何用 CSS 画一个会动的 loading 动画”!

评论 0

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