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

Dev前端
2025-12-16 11:14
阅读 690

大家好,我是小林,一名在大厂干了3年前端开发的工程师,业余时间也在B站做技术UP主。最近在评论区和私信里,收到不少零基础同学的问题:“现在写样式到底该用传统的 CSS 文件,还是用 CSS-in-JS?”、“简历上写哪种技术更有竞争力?”、“这两种方式有什么区别?”

我当初学前端的时候也踩过类似的坑——一开始只会 <style> 标签内写样式,后来学了 .css 文件,再后来接触 React 项目,突然冒出一堆 styled-componentsemotion 这些陌生名词,完全懵了。

所以今天这篇技术分享,就是专门为完全零基础的同学写的。我会用最直白的语言,带你从“什么是样式”开始,一步步理解 CSS-in-JS 和传统 CSS 的区别,并通过一个实战项目让你亲手体验两者的差异。最后还会告诉你:在简历上该怎么写、怎么选,才不被面试官问住!


一、为什么会有两种写样式的方式?

1.1 传统 CSS:网页的“衣服设计师”

想象一下,你有一个 HTML 元素(比如一个按钮),你想给它穿一件红色的衣服、加个圆角。在传统方式中,你会:

  1. 写一个 .button { color: red; border-radius: 8px; } 的规则
  2. 在 HTML 中给按钮加上 class="button"

这就是 传统 CSS —— 样式和结构分离,像设计师和裁缝分工合作。

✅ 优点:

  • 简单直观,浏览器原生支持
  • 学习成本低,适合静态页面
  • 性能好(直接由浏览器解析)

❌ 缺点:

  • 全局作用域:.button 可能在其他地方被意外覆盖
  • 难以动态化:比如“根据用户主题切换颜色”需要 JavaScript 手动操作 class
  • 组件复用困难:React/Vue 组件希望“样式跟着组件走”,但 CSS 是全局的

1.2 CSS-in-JS:把样式“塞进”JavaScript 里

为了解决上述问题,社区发明了 CSS-in-JS —— 直接在 JS 代码里写样式。

比如用 styled-components(一个流行的 CSS-in-JS 库):

import styled from 'styled-components';

const RedButton = styled.button`
  color: red;
  border-radius: 8px;
`;

你看,样式直接写在 JS 变量里!这个 RedButton 就是一个自带样式的 React 组件。

✅ 优点:

  • 自动作用域隔离(每个组件样式独立)
  • 支持动态样式(比如 props => color: ${props.theme}
  • 更符合组件化思想

❌ 缺点:

  • 需要额外依赖(增加包体积)
  • 学习曲线稍陡(要理解模板字符串、props 等)
  • 调试不如传统 CSS 直观(开发者工具里类名是随机的)

📌 一句话总结
传统 CSS = 外部文件管理样式
CSS-in-JS = 在 JS 里直接定义样式


二、环境准备:搭建你的第一个项目

我们来分别创建两个小项目,体验两种方式。

2.1 准备工作

你需要安装:

  • Node.js(推荐 v18+)
  • 一个代码编辑器(如 VS Code)

打开终端,执行:

# 创建项目文件夹
mkdir css-comparison
cd css-comparison

# 初始化 npm 项目
npm init -y

2.2 传统 CSS 项目

# 创建传统 CSS 项目
mkdir traditional-css
cd traditional-css

# 创建 index.html 和 style.css
echo '<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <button class="my-button">传统按钮</button>
</body>
</html>' > index.html

echo '.my-button {
  background: blue;
  color: white;
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}' > style.css

双击 index.html 用浏览器打开,就能看到蓝色按钮!

2.3 CSS-in-JS 项目(使用 Vite + React)

CSS-in-JS 主要在 React 等框架中使用。我们用 Vite 快速搭建:

# 回到根目录
cd ..

# 使用 Vite 创建 React 项目
npm create vite@latest css-in-js-demo -- --template react
cd css-in-js-demo
npm install

# 安装 styled-components
npm install styled-components

# 启动开发服务器
npm run dev

Vite 会输出一个本地地址(如 http://localhost:5173),打开即可看到默认页面。


三、核心概念对比(附代码示例)

3.1 如何定义样式?

方式 代码示例 特点
传统 CSS css<br>.btn {<br> color: red;<br>} 全局作用域,需手动管理命名
CSS-in-JS js<br>const Btn = styled.button`<br> color: red;<br>`; 自动局部作用域,样式绑定到组件

3.2 如何传递动态样式?

假设我们要做一个“根据 props 改变颜色”的按钮。

传统 CSS 做法(麻烦!):

<!-- HTML -->
<button class="btn btn-red">红按钮</button>
<button class="btn btn-blue">蓝按钮</button>
/* CSS */
.btn-red { background: red; }
.btn-blue { background: blue; }

→ 需要预先定义所有可能的 class,不灵活!

CSS-in-JS 做法(优雅!):

const DynamicButton = styled.button`
  background: ${props => props.color};
  color: white;
`;

// 使用
<DynamicButton color="red">红按钮</DynamicButton>
<DynamicButton color="blue">蓝按钮</DynamicButton>

→ 样式直接接收 props,动态生成!

3.3 如何处理嵌套和伪类?

传统 CSS:

.card {
  padding: 16px;
}
.card:hover {
  box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.card .title {
  font-size: 18px;
}

CSS-in-JS(以 styled-components 为例):

const Card = styled.div`
  padding: 16px;
  
  &:hover {
    box-shadow: 0 4px 8px rgba(0,0,0,0.2);
  }

  .title {
    font-size: 18px;
  }
`;

注意:虽然可以写 .title,但更推荐用另一个 styled 组件,避免回到 class 依赖的老路。


四、实战项目:做一个主题切换按钮

我们现在用两种方式各做一个“点击切换亮/暗主题”的按钮。

4.1 传统 CSS 实现

思路

  1. 定义两个 class:.light-theme, .dark-theme
  2. 用 JS 切换 body 的 class
  3. 通过 CSS 后代选择器应用不同样式
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="theme.css">
</head>
<body class="light-theme">
  <button id="toggleBtn">切换主题</button>
  <script src="app.js"></script>
</body>
</html>
/* theme.css */
.light-theme {
  background: white;
  color: black;
}
.dark-theme {
  background: #121212;
  color: white;
}

.light-theme button {
  background: #e0e0e0;
}
.dark-theme button {
  background: #424242;
  color: white;
}
// app.js
let isDark = false;
document.getElementById('toggleBtn').addEventListener('click', () => {
  const body = document.body;
  if (isDark) {
    body.className = 'light-theme';
  } else {
    body.className = 'dark-theme';
  }
  isDark = !isDark;
});

✅ 能用,但:

  • 样式分散在 CSS 和 JS 中
  • 主题逻辑和 UI 强耦合
  • 如果有多个组件,每个都要写 .light-theme .xxx

4.2 CSS-in-JS 实现(React + styled-components)

思路

  1. 用 React 的 useState 管理主题状态
  2. 将主题通过 ThemeProvider 全局传递
  3. styled 组件直接读取主题变量
// main.jsx
import React, { useState } from 'react';
import { createRoot } from 'react-dom/client';
import { ThemeProvider } from 'styled-components';

const lightTheme = { bg: 'white', text: 'black', btnBg: '#e0e0e0' };
const darkTheme = { bg: '#121212', text: 'white', btnBg: '#424242' };

function App() {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  };

  return (
    <ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}>
      <div style={{ padding: '20px' }}>
        <ToggleThemeButton onClick={toggleTheme} />
      </div>
    </ThemeProvider>
  );
}

// 定义带样式的按钮
import styled from 'styled-components';

const ToggleThemeButton = styled.button`
  background: ${props => props.theme.btnBg};
  color: ${props => props.theme.text};
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
`;

createRoot(document.getElementById('root')).render(<App />);

✅ 优势明显:

  • 样式和逻辑都在 JS 中,高内聚
  • 主题变量集中管理
  • 每个组件自动适配主题,无需重复写选择器

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

Q1:CSS-in-JS 会不会很慢?

:早期确实有性能问题,但现在主流库(如 emotionstyled-components)都做了优化:

  • 样式只生成一次
  • 自动去重
  • 支持服务端渲染(SSR)

除非是超大型应用,否则性能差异几乎感知不到。

Q2:简历上该写哪种技术?

:看岗位要求!

  • 如果面传统企业站、CMS 系统 → 强调你精通 Sass、PostCSS、BEM 命名规范
  • 如果面React 技术栈的大厂 → 写上 “熟悉 styled-components / emotion,实现主题系统与动态样式”

💡 避坑建议:不要写“我会 CSS-in-JS”,而要写“使用 styled-components 实现了可复用的主题切换组件,提升团队开发效率” —— 结果导向才加分!

Q3:能不能混用两种方式?

:可以,但不推荐!

  • 混用会导致样式来源混乱
  • 调试困难(某个元素为啥是这个颜色?查半天发现是全局 CSS 覆盖了)

建议:一个项目统一一种方案

Q4:CSS Modules 算哪边?

:CSS Modules 是传统 CSS 的“升级版”,它通过编译时生成唯一 class 名实现局部作用域,属于“传统阵营的现代化方案”。如果你不想引入 JS 样式库,又想要作用域隔离,它是很好的折中选择。


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

6.1 零基础学习路径

  1. 先掌握传统 CSS

    • 学盒模型、Flex、Grid
    • 掌握 BEM 命名规范
    • 了解 Sass/Less 预处理器
  2. 再学组件化框架(React/Vue)

    • 理解组件、props、state
  3. 最后接触 CSS-in-JS

    • styled-componentsemotion 入手
    • 尝试实现动态主题、响应式样式

6.2 避坑指南(我踩过的雷)

  • ❌ 不要一上来就学 CSS-in-JS!基础 CSS 不牢,你会连“为什么需要 CSS-in-JS”都不懂。
  • ❌ 不要为了用新技术而用!如果项目是静态页,传统 CSS 更合适。
  • ✅ 在个人项目中尝试 CSS-in-JS,把它写进简历的“项目经验”里,比单纯写“了解”有力得多。

6.3 推荐学习资源

  • MDN Web Docs(免费,权威)
  • 《CSS 权威指南》(书籍)
  • 我的 B 站频道【小林前端课】(搜索“CSS-in-JS 实战”)
  • styled-components 官方文档(英文,但示例丰富)

结语

CSS-in-JS 和传统 CSS 不是对立关系,而是不同场景下的工具选择。就像你会用螺丝刀也会用锤子,关键看钉子是什么类型。

作为前端开发者,理解问题本质比追逐新潮更重要。当你能说出“我们项目用传统 CSS + CSS Modules,因为团队习惯且性能优先”,或者“我们用 emotion 实现了设计系统的 token 化管理”,面试官就知道:你是个有思考的工程师。

最后,别忘了:技术分享的价值在于帮助他人少走弯路。如果你觉得这篇文章对你有帮助,欢迎点赞、转发,也欢迎来我 B 站评论区交流!

祝你 coding happy,offer 拿到手软!🎉

评论 0

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