React CSS 方案对比:SCSS vs React CSS-in-JS
🎯 核心问题
SCSS 比 React 的 CSS 还强大吗?React 还有更厉害的 CSS 吗?
答案: React 有很多更强大的 CSS 方案,它们各有优势。SCSS 是预处理器,而 React 的 CSS-in-JS 是运行时/编译时方案,功能更强大。
📊 方案对比总览
| 方案 |
类型 |
学习曲线 |
性能 |
功能强大度 |
流行度 |
| SCSS |
预处理器 |
⭐⭐ |
⭐⭐⭐⭐ |
⭐⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
| CSS Modules |
编译时 |
⭐⭐ |
⭐⭐⭐⭐⭐ |
⭐⭐⭐ |
⭐⭐⭐⭐ |
| Styled Components |
CSS-in-JS |
⭐⭐⭐ |
⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
| Emotion |
CSS-in-JS |
⭐⭐⭐ |
⭐⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
⭐⭐⭐⭐ |
| Tailwind CSS |
工具类 |
⭐⭐ |
⭐⭐⭐⭐⭐ |
⭐⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
| StyleX |
零运行时 |
⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
⭐⭐⭐⭐ |
⭐⭐ |
1. SCSS(你当前使用的)
特点
- ✅ 预处理器:编译时转换为 CSS
- ✅ 功能强大:变量、嵌套、函数、混入等
- ✅ 性能好:编译后就是普通 CSS
- ✅ 生态成熟:插件和工具丰富
代码示例
// device.scss
$primary-color: #0769fb;
.device-container {
background-color: $primary-color;
.device-update {
padding: 16px;
}
}
// device.jsx
import './device.scss'
function Device() {
return <div className="device-container">...</div>
}
优势
- ✅ 编译时处理,运行时性能好
- ✅ 功能完整(变量、函数、循环等)
- ✅ 学习成本低
- ✅ 浏览器兼容性好
劣势
- ❌ 无法在 JS 中动态修改样式
- ❌ 无法根据 props 动态生成样式
- ❌ 样式和组件分离
2. CSS Modules(编译时方案)
特点
- ✅ 局部作用域:自动生成唯一类名
- ✅ 类型安全:TypeScript 支持好
- ✅ 性能优秀:编译时处理
- ✅ 零运行时开销
代码示例
/* device.module.css */
.container {
background-color: #0769fb;
}
.title {
font-size: 20px;
}
// device.jsx
import styles from './device.module.css'
function Device() {
return (
<div className={styles.container}>
<h1 className={styles.title}>设备</h1>
</div>
)
}
优势
- ✅ 自动作用域隔离,避免样式冲突
- ✅ 性能好,编译时处理
- ✅ TypeScript 支持好
- ✅ 可以配合 SCSS 使用
劣势
3. Styled Components(CSS-in-JS)⭐ 最流行
特点
- ✅ CSS-in-JS:样式写在 JS 中
- ✅ 动态样式:根据 props 动态生成
- ✅ 组件化:样式和组件绑定
- ✅ 主题支持:内置主题系统
安装
npm install styled-components
代码示例
import styled from 'styled-components'
// 创建样式组件
const DeviceContainer = styled.div`
width: 100%;
height: 100%;
background-color: ${props => props.bgColor || '#0769fb'};
display: flex;
align-items: center;
justify-content: center;
&:hover {
background-color: ${props => props.hoverColor || '#0550d0'};
}
`
const Title = styled.h1`
font-size: ${props => props.size || '20px'};
color: ${props => props.theme.primaryColor};
`
// 使用
function Device({ isActive }) {
return (
<DeviceContainer
bgColor={isActive ? '#28a745' : '#0769fb'}
hoverColor="#0550d0"
>
<Title size="24px">设备列表</Title>
</DeviceContainer>
)
}
// 主题支持
const theme = {
primaryColor: '#0769fb',
spacing: '16px'
}
function App() {
return (
<ThemeProvider theme={theme}>
<Device />
</ThemeProvider>
)
}
优势
- ✅ 动态样式:根据 props/state 动态生成
- ✅ 组件化:样式和组件绑定,易维护
- ✅ 主题系统:内置主题支持
- ✅ TypeScript 支持好
- ✅ 自动处理浏览器前缀
劣势
- ❌ 运行时开销(但很小)
- ❌ 学习曲线较陡
- ❌ 调试稍困难(生成的类名)
4. Emotion(CSS-in-JS)⭐ 性能更好
特点
- ✅ 性能优化:比 styled-components 更快
- ✅ 灵活:支持多种写法
- ✅ 体积小:247KB
- ✅ React 18 支持好
安装
npm install @emotion/react @emotion/styled
代码示例
import { css } from '@emotion/react'
import styled from '@emotion/styled'
// 方式1:css prop
const containerStyle = css`
width: 100%;
background-color: #0769fb;
&:hover {
background-color: #0550d0;
}
`
function Device() {
return <div css={containerStyle}>设备</div>
}
// 方式2:styled components
const DeviceContainer = styled.div`
width: 100%;
background-color: ${props => props.bgColor};
&:hover {
transform: scale(1.05);
}
`
// 方式3:动态样式
function Device({ isActive }) {
return (
<div
css={css`
background-color: ${isActive ? '#28a745' : '#0769fb'};
transition: all 0.3s;
`}
>
设备
</div>
)
}
优势
- ✅ 性能比 styled-components 好
- ✅ 支持多种写法
- ✅ 体积更小
- ✅ SSR 支持好
劣势
- ❌ 社区相对较小
- ❌ 文档不如 styled-components 完善
5. Tailwind CSS(工具类)⭐ 最流行
特点
- ✅ 工具类:预定义的 CSS 类
- ✅ 按需生成:只生成使用的样式
- ✅ 性能极佳:编译时处理
- ✅ 开发速度快:无需写 CSS
安装
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
代码示例
// 纯工具类
function Device() {
return (
<div className="w-full h-full bg-blue-500 flex items-center justify-center hover:bg-blue-600 transition-colors">
<h1 className="text-white text-2xl font-bold">设备列表</h1>
</div>
)
}
// 配合 CSS Modules
// device.module.css
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.device-card {
@apply bg-blue-500 p-4 rounded-lg shadow-lg;
}
}
优势
- ✅ 开发速度快:无需写 CSS
- ✅ 性能好:按需生成
- ✅ 一致性:设计系统统一
- ✅ 体积小:只包含使用的样式
- ✅ 学习成本低
劣势
- ❌ HTML 类名可能很长
- ❌ 需要记忆工具类
- ❌ 复杂动画需要额外配置
6. StyleX(Meta 零运行时)
特点
- ✅ 零运行时:编译时转换为 CSS
- ✅ 类型安全:TypeScript 支持好
- ✅ 性能最佳:无运行时开销
- ✅ Meta 开发:Facebook 出品
安装
npm install @stylexjs/stylex
代码示例
import stylex from '@stylexjs/stylex'
const styles = stylex.create({
container: {
width: '100%',
backgroundColor: '#0769fb',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
title: {
fontSize: '20px',
color: 'white',
},
})
function Device() {
return (
<div {...stylex.props(styles.container)}>
<h1 {...stylex.props(styles.title)}>设备</h1>
</div>
)
}
优势
- ✅ 零运行时开销
- ✅ 类型安全
- ✅ 性能最佳
- ✅ Meta 支持
劣势
- ❌ 相对较新,生态不成熟
- ❌ 学习曲线陡
- ❌ 文档较少
🎯 功能对比
动态样式(根据 props/state)
| 方案 |
支持度 |
| SCSS |
❌ 不支持 |
| CSS Modules |
❌ 不支持 |
| Styled Components |
✅✅✅ 完全支持 |
| Emotion |
✅✅✅ 完全支持 |
| Tailwind CSS |
⚠️ 需要配合 JS |
| StyleX |
✅ 支持 |
主题支持
| 方案 |
支持度 |
| SCSS |
⚠️ 需要手动实现 |
| CSS Modules |
⚠️ 需要手动实现 |
| Styled Components |
✅✅✅ 内置支持 |
| Emotion |
✅✅✅ 内置支持 |
| Tailwind CSS |
✅ 配置支持 |
| StyleX |
⚠️ 需要手动实现 |
性能
| 方案 |
运行时开销 |
编译时优化 |
| SCSS |
✅ 无 |
✅ 是 |
| CSS Modules |
✅ 无 |
✅ 是 |
| Styled Components |
⚠️ 有 |
❌ 否 |
| Emotion |
⚠️ 有(较小) |
⚠️ 部分 |
| Tailwind CSS |
✅ 无 |
✅ 是 |
| StyleX |
✅ 无 |
✅ 是 |
TypeScript 支持
| 方案 |
支持度 |
| SCSS |
⚠️ 基础 |
| CSS Modules |
✅✅✅ 完美 |
| Styled Components |
✅✅✅ 完美 |
| Emotion |
✅✅✅ 完美 |
| Tailwind CSS |
✅✅ 很好 |
| StyleX |
✅✅✅ 完美 |
💡 实际应用示例对比
场景:根据状态动态改变样式
SCSS(不支持动态)
// 需要写多个类
.device-active { background: #28a745; }
.device-inactive { background: #0769fb; }
<div className={isActive ? 'device-active' : 'device-inactive'}>
Styled Components(完全支持)
const Device = styled.div`
background-color: ${props => props.isActive ? '#28a745' : '#0769fb'};
transition: all 0.3s;
`
<Device isActive={isActive}>设备</Device>
Tailwind CSS(需要配合 JS)
<div className={`${isActive ? 'bg-green-500' : 'bg-blue-500'} transition-colors`}>
🏆 推荐方案
1. 小型项目 → SCSS
2. 中型项目 → CSS Modules + SCSS
- ✅ 作用域隔离
- ✅ 性能好
- ✅ TypeScript 支持好
3. 大型项目(需要动态样式) → Styled Components / Emotion
4. 快速开发 → Tailwind CSS
5. 性能优先 → StyleX
📝 总结
SCSS vs React CSS-in-JS
| 特性 |
SCSS |
React CSS-in-JS |
| 动态样式 |
❌ |
✅ |
| 组件绑定 |
❌ |
✅ |
| 主题系统 |
⚠️ |
✅ |
| 运行时性能 |
✅ |
⚠️ |
| 编译时性能 |
✅ |
⚠️ |
| 学习曲线 |
⭐⭐ |
⭐⭐⭐ |
| 功能强大度 |
⭐⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
结论
- SCSS 是预处理器,功能强大但无法动态修改样式
- React CSS-in-JS(Styled Components/Emotion) 更强大,支持动态样式、主题、组件绑定
- Tailwind CSS 适合快速开发,性能好
- StyleX 性能最佳,但生态不成熟
建议:
- 如果不需要动态样式 → 继续用 SCSS
- 如果需要动态样式和主题 → 使用 Styled Components 或 Emotion
- 如果追求性能 → 使用 Tailwind CSS 或 StyleX
🚀 迁移建议
从 SCSS 迁移到 Styled Components
// 之前:SCSS
// device.scss
.device-container {
background-color: $primary-color;
}
// device.jsx
import './device.scss'
<div className="device-container">
// 之后:Styled Components
import styled from 'styled-components'
const DeviceContainer = styled.div`
background-color: ${props => props.theme.primaryColor};
`
<DeviceContainer>
混合使用(推荐)
// 全局样式用 SCSS
import './global.scss'
// 组件样式用 Styled Components
const Button = styled.button`...`
📚 学习资源