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

二分查找猫
2025-12-17 16:59
阅读 2157

大家好!我是正在读计算机研究生的一名前端爱好者,平时喜欢写技术博客帮助刚入门的新朋友。今天想和大家聊聊一个我当初学前端时非常困惑的问题:CSS 到底该怎么写?

在 React、Vue 等现代框架流行后,“CSS-in-JS” 这个词频繁出现在教程里,而传统的 .css 文件又好像没被淘汰。到底该用哪种方式写样式?它们有什么区别?新手该如何选择?

这篇文章就是为完全零基础的同学准备的。我会用最简单的语言、最实用的例子,带你一步步搞懂这两种主流样式方案,并给出我的最佳实践建议。希望你能看完后不再迷茫!


一、什么是 CSS-in-JS 和传统 CSS?

传统 CSS(Classic CSS)

这是你最早接触的写法:在一个 .css 文件里写样式,然后在 HTML 或组件中通过 class 引用。

<!-- index.html -->
<div class="header">欢迎来到我的网站</div>
/* styles.css */
.header {
  color: blue;
  font-size: 24px;
}

优点:简单直观,浏览器原生支持,学习成本极低。

CSS-in-JS

这是一种用 JavaScript 写 CSS 的方式。样式不再是独立文件,而是直接写在 JS/TS 组件内部,通常借助第三方库(如 styled-components、Emotion)实现。

// Header.jsx (React 示例)
import styled from 'styled-components';

const Header = styled.div`
  color: blue;
  font-size: 24px;
`;

export default function App() {
  return <Header>欢迎来到我的网站</Header>;
}

优点:样式与组件强绑定、自动避免命名冲突、支持动态样式、便于按需加载。

💡 我当初学的时候以为 CSS-in-JS 是“取代”传统 CSS 的新技术,其实不是!它们是不同场景下的工具选择,就像螺丝刀和锤子,各有用途。


二、开发环境准备(5分钟快速搭建)

为了能实际运行代码,我们需要一个最小化的前端开发环境。这里以 React + Vite 为例(Vite 启动快,适合新手)。

步骤 1:安装 Node.js

https://nodejs.org 下载 LTS 版本(长期支持版),安装即可。

验证是否安装成功:

node -v  # 应输出 v18.x 或更高
npm -v   # 应输出 8.x 或更高

步骤 2:创建项目

打开终端,执行:

npm create vite@latest my-style-project -- --template react
cd my-style-project
npm install

步骤 3:安装 CSS-in-JS 库(可选)

如果你想尝试 CSS-in-JS,比如 styled-components

npm install styled-components

⚠️ 注意:Vite 默认不支持 styled-components 的 SSR(服务端渲染),但对学习完全够用。如果你只学传统 CSS,这步可以跳过。

步骤 4:启动项目

npm run dev

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


三、核心概念对比:一张表看懂区别

对比项 传统 CSS CSS-in-JS
文件位置 独立 .css 文件 写在 JS/TS 组件内
作用域 全局(容易冲突) 局部(自动隔离)
动态样式 需要 JS 操作 class 直接传 props 控制
性能 静态文件,缓存友好 运行时生成,略慢
学习曲线 极低 中等(需理解 JS 作用域)
适用场景 静态页面、简单项目 复杂组件、需要主题切换

关键概念解释

1. 作用域(Scope)

  • 传统 CSS 中,.button 在任何地方都会生效,如果两个组件都用了 .button,样式会互相影响。
  • CSS-in-JS 自动生成唯一类名(如 sc-1a2b3c4),确保样式只作用于当前组件。

2. 动态样式

传统 CSS 要实现“根据状态变色”,得写多个 class:

.button { background: gray; }
.button.primary { background: blue; }
<div className={`button ${isPrimary ? 'primary' : ''}`}>按钮</div>

而 CSS-in-JS 可以直接:

const Button = styled.button`
  background: ${props => props.primary ? 'blue' : 'gray'};
`;
<Button primary={true}>按钮</Button>

更简洁,逻辑更集中!


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

我们来动手写一个同时用两种方式实现的卡片组件,体验差异。

项目结构

src/
├── components/
│   ├── CardTraditional.jsx  // 传统 CSS 实现
│   └── CardStyled.jsx       // CSS-in-JS 实现
├── styles/
│   └── card.css             // 传统 CSS 文件
└── App.jsx

方式一:传统 CSS 实现

1. 创建 styles/card.css

.card {
  padding: 16px;
  border-radius: 8px;
  margin: 10px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.card.light {
  background-color: white;
  color: black;
}

.card.dark {
  background-color: #333;
  color: white;
}

2. 创建 components/CardTraditional.jsx

import '../styles/card.css';

export default function CardTraditional({ theme = 'light', children }) {
  return (
    <div className={`card ${theme}`}>
      {children}
    </div>
  );
}

3. 在 App.jsx 中使用

import CardTraditional from './components/CardTraditional';

export default function App() {
  return (
    <div>
      <CardTraditional theme="light">浅色卡片</CardTraditional>
      <CardTraditional theme="dark">深色卡片</CardTraditional>
    </div>
  );
}

✅ 优点:清晰分离关注点,设计师可以直接改 CSS。
❌ 缺点:需要手动管理 class 名,容易拼错或冲突。


方式二:CSS-in-JS 实现(使用 styled-components)

1. 安装依赖(如果还没装)

npm install styled-components

2. 创建 components/CardStyled.jsx

import styled from 'styled-components';

const StyledCard = styled.div`
  padding: 16px;
  border-radius: 8px;
  margin: 10px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  
  /* 根据 props 动态设置样式 */
  background-color: ${props => props.theme === 'dark' ? '#333' : 'white'};
  color: ${props => props.theme === 'dark' ? 'white' : 'black'};
`;

export default function CardStyled({ theme = 'light', children }) {
  return <StyledCard theme={theme}>{children}</StyledCard>;
}

3. 在 App.jsx 中替换使用

import CardStyled from './components/CardStyled';

export default function App() {
  return (
    <div>
      <CardStyled theme="light">浅色卡片</CardStyled>
      <CardStyled theme="dark">深色卡片</CardStyled>
    </div>
  );
}

✅ 优点:样式和逻辑在一起,修改方便,无命名冲突。
❌ 缺点:增加了 JS 体积,调试时类名是随机的。

🔍 小技巧:在 styled-components 中,你可以用 attrswithConfig 自定义生成的 class 名,方便调试。


五、新手常见问题解答(FAQ)

Q1:CSS-in-JS 会不会让网页变慢?

:对于中小型项目,性能差异几乎感知不到。现代库(如 Emotion)做了很多优化。只有在极端高性能场景(如动画密集型应用)才需谨慎。

Q2:我该从哪种开始学?

强烈建议先掌握传统 CSS!因为:

  • 所有前端框架都支持它
  • 面试必考
  • 是理解 CSS 原理的基础

等你熟悉组件化开发后,再根据项目需求尝试 CSS-in-JS。

Q3:CSS Modules 是什么?属于哪一类?

:CSS Modules 是传统 CSS 的“升级版”。它通过编译把 .card 变成 .card_hash123,实现局部作用域。它仍属于传统 CSS 范畴,只是加了作用域隔离。

/* card.module.css */
.card { color: red; }
import styles from './card.module.css';
<div className={styles.card}>...</div>

Q4:Tailwind CSS 算哪一种?

:Tailwind 是“原子化 CSS”,既不是传统 CSS(不用写 .class{}),也不是 CSS-in-JS(不写在 JS 里)。它是第三种流派,用工具类组合样式。


六、我的最佳实践建议

结合我带实习生的经验,给出以下建议:

🟢 推荐使用传统 CSS 的场景:

  • 静态营销页面(如公司官网)
  • 小型个人项目
  • 团队中有设计师直接交付 CSS
  • 学习阶段(打好基础最重要)

🟢 推荐使用 CSS-in-JS 的场景:

  • 复杂的 React/Vue 组件库开发
  • 需要主题切换、动态皮肤
  • 微前端架构(避免样式污染)
  • 团队统一使用现代框架

🔧 我的个人配置偏好

  • 小项目:传统 CSS + CSS Modules
  • 大型 React 项目:Emotion(比 styled-components 更轻量)
  • 不推荐在 Vue 中强行用 CSS-in-JS(Vue 的 <style scoped> 已足够好)

七、下一步学习路径

  1. 巩固基础:深入学习 CSS 盒模型、Flex/Grid 布局、响应式设计。
  2. 进阶工具:了解 PostCSS、Sass(传统 CSS 的增强工具)。
  3. 探索现代方案:尝试 Tailwind CSS、UnoCSS 等原子化方案。
  4. 性能优化:学习 Critical CSS、CSS 代码分割等高级技巧。

📌 避坑指南:不要一上来就追求“最新技术”。我见过太多新手跳过 CSS 基础,直接用 CSS-in-JS,结果连 position 都不会用,写出的布局全是 margin 硬调。扎实的基础永远是最快的捷径


结语

写这篇教程,是因为我深知初学者面对技术选型时的焦虑。CSS-in-JS 并不是“更好”的 CSS,而是“更适合某些场景”的 CSS。

记住:工具没有好坏,只有合不合适。

希望这篇文章能帮你理清思路。如果你有任何疑问,欢迎在评论区留言——虽然这是篇博客,但我真的会看 😄

加油,未来的前端工程师!你的第一个 div 已经写得很棒了。


本文约 3220 字,由一名 211 计算机研究生撰写,坚持做对新人友好的技术分享。

评论 0

最热最新
暂无评论
二分查找猫Lv.1
0
影响力
0
文章
0
粉丝