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

日志切割师
2025-12-17 00:01
阅读 721

作者说:我当初学前端的时候,光是搞懂“为什么有那么多写样式的办法”就花了好几天。培训班老师讲得很快,一会儿 class,一会儿 styled-components,我完全懵了。后来在做实际项目(包括和 Springboot 后端联调)时才真正理解不同方案的优劣。今天,我就以一个“过来人”的身份,用最通俗的语言、最真实的代码,带你一步步搞清楚:到底该用哪种方式写 CSS?


一、什么是 CSS-in-JS?它和传统 CSS 有什么区别?

1.1 传统 CSS 是什么?

传统 CSS 就是我们最熟悉的 .css 文件。你写 HTML,然后在 <head> 里引入一个 .css 文件,通过 classid 来给元素加样式。

<!-- 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-components
  • Emotion
  • Linaria(编译时方案)

核心区别一句话总结
传统 CSS 是“先写样式,再挂到 HTML 上”;
CSS-in-JS 是“在组件里直接定义样式,自动绑定”。


二、环境准备:搭建一个可运行的项目

我们用一个最小化的 React 项目来演示两种方案。即使你没接触过 React,也不用怕——我会解释每一步。

2.1 安装 Node.js 和 npm

  1. https://nodejs.org 下载 LTS 版本(推荐 18.x 或 20.x)
  2. 安装后,在终端运行:
    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 上有现成项目可以参考吗?

:当然!推荐两个资源:

💡 搜索技巧:在 GitHub 搜索 react css-in-js examplereact springboot frontend,能找到大量实战项目。


六、学习建议与避坑指南

🧭 学习路径建议

  1. 第一阶段:熟练使用传统 CSS + HTML。能独立写静态页面。
  2. 第二阶段:学习 React/Vue 基础,理解组件化思想。
  3. 第三阶段:尝试 CSS Modules(CRA 已内置支持)。
  4. 第四阶段:再接触 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

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