BEST_CSS_VS_SCSS.md 9.8 KB

功能最强大的 CSS 方案 vs SCSS

🏆 功能最强大的 CSS 方案:Styled Components(CSS-in-JS)

Styled Components 是目前功能最强大的 React CSS 方案,支持动态样式、主题系统、组件绑定等 SCSS 无法实现的功能。


📊 核心对比

功能 SCSS Styled Components
动态样式(根据 props/state) ✅✅✅
组件绑定 ✅✅✅
主题系统 ⚠️ 手动实现 ✅✅✅ 内置
条件样式 ✅✅✅
运行时修改 ✅✅✅
TypeScript 支持 ⚠️ 基础 ✅✅✅ 完美
变量系统 ✅✅✅ ✅✅✅
嵌套 ✅✅✅ ✅✅✅
函数/混入 ✅✅✅ ✅✅✅
编译时性能 ✅✅✅ ⚠️ 运行时
运行时性能 ✅✅✅ ⚠️ 有开销

🚀 Styled Components 的核心优势

1. 动态样式(SCSS 无法实现)

SCSS(静态)

// device.scss
.device-active { background: #28a745; }
.device-inactive { background: #0769fb; }
// 需要手动切换类名
<div className={isActive ? 'device-active' : 'device-inactive'}>

Styled Components(动态)

import styled from 'styled-components'

const Device = styled.div`
  background-color: ${props => props.isActive ? '#28a745' : '#0769fb'};
  color: ${props => props.isActive ? 'white' : 'black'};
  transform: ${props => props.isActive ? 'scale(1.05)' : 'scale(1)'};
  transition: all 0.3s;
`

// 直接使用,自动根据 props 变化
<Device isActive={isActive}>设备</Device>

优势: 样式完全由 JavaScript 控制,可以根据任何条件动态生成。


2. 主题系统(SCSS 需要手动实现)

SCSS(手动实现)

// 需要写多个主题类
.theme-light { background: #fff; color: #000; }
.theme-dark { background: #1a1a1a; color: #fff; }
<div className={`container ${theme === 'dark' ? 'theme-dark' : 'theme-light'}`}>

Styled Components(内置主题)

import styled, { ThemeProvider } from 'styled-components'

const Container = styled.div`
  background-color: ${props => props.theme.bg};
  color: ${props => props.theme.text};
`

const theme = {
  light: { bg: '#fff', text: '#000' },
  dark: { bg: '#1a1a1a', text: '#fff' }
}

// 一键切换主题
<ThemeProvider theme={theme[currentTheme]}>
  <Container>内容</Container>
</ThemeProvider>

优势: 内置主题系统,切换主题无需修改组件代码。


3. 组件绑定(SCSS 样式和组件分离)

SCSS(分离)

// device.scss
.device-container { }
.device-title { }
.device-button { }
// device.jsx
import './device.scss'
<div className="device-container">
  <h1 className="device-title">标题</h1>
  <button className="device-button">按钮</button>
</div>

Styled Components(绑定)

import styled from 'styled-components'

const DeviceContainer = styled.div`
  width: 100%;
  background-color: #0769fb;
`

const DeviceTitle = styled.h1`
  font-size: 24px;
  color: white;
`

const DeviceButton = styled.button`
  padding: 12px 24px;
  background: white;
  border: none;
  border-radius: 4px;
`

// 样式和组件完全绑定,不会冲突
function Device() {
  return (
    <DeviceContainer>
      <DeviceTitle>标题</DeviceTitle>
      <DeviceButton>按钮</DeviceButton>
    </DeviceContainer>
  )
}

优势: 样式和组件绑定,自动作用域隔离,不会产生样式冲突。


4. 条件样式(SCSS 需要写多个类)

SCSS(多个类)

.button { }
.button-primary { background: blue; }
.button-danger { background: red; }
.button-large { padding: 20px; }
.button-small { padding: 10px; }
<button className={`button button-${type} button-${size}`}>

Styled Components(条件逻辑)

const Button = styled.button`
  padding: ${props => props.size === 'large' ? '20px' : '10px'};
  background-color: ${props => {
    if (props.variant === 'primary') return '#0769fb';
    if (props.variant === 'danger') return '#dc3545';
    return '#6c757d';
  }};
  
  ${props => props.disabled && `
    opacity: 0.5;
    cursor: not-allowed;
  `}
`

<Button variant="primary" size="large" disabled={false}>
  按钮
</Button>

优势: 使用 JavaScript 逻辑,更灵活强大。


5. 响应式设计(更灵活)

SCSS(媒体查询)

.container {
  width: 100%;
  
  @media (max-width: 768px) {
    width: 50%;
  }
}

Styled Components(函数式)

const Container = styled.div`
  width: 100%;
  
  ${props => props.theme.breakpoints.md} {
    width: 50%;
  }
  
  // 或者使用 props
  width: ${props => props.isMobile ? '100%' : '50%'};
`

优势: 可以根据 props 动态调整,不局限于媒体查询。


6. TypeScript 完美支持

SCSS(无类型)

// 无法类型检查
.container { }

Styled Components(类型安全)

interface ButtonProps {
  variant?: 'primary' | 'danger' | 'success';
  size?: 'small' | 'medium' | 'large';
}

const Button = styled.button<ButtonProps>`
  background-color: ${props => {
    // TypeScript 会自动提示 variant 的值
    switch (props.variant) {
      case 'primary': return '#0769fb';
      case 'danger': return '#dc3545';
      default: return '#6c757d';
    }
  }};
`

优势: 完整的 TypeScript 支持,类型安全,自动补全。


💪 功能对比总结

SCSS 能做的

  • ✅ 变量
  • ✅ 嵌套
  • ✅ 函数/混入
  • ✅ 编译时处理

Styled Components 能做的(SCSS 无法实现)

  • 动态样式:根据 props/state 实时变化
  • 主题系统:内置主题切换
  • 组件绑定:样式和组件绑定
  • 条件样式:JavaScript 逻辑控制
  • 运行时修改:动态生成样式
  • TypeScript:完美类型支持

🎯 实际应用场景对比

场景1:根据状态改变样式

SCSS

.device-online { background: green; }
.device-offline { background: red; }
.device-unknown { background: gray; }
<div className={`device-${status}`}>

Styled Components

const Device = styled.div`
  background-color: ${props => {
    if (props.status === 'online') return 'green';
    if (props.status === 'offline') return 'red';
    return 'gray';
  }};
`

<Device status={status}>

优势: 无需预定义所有状态类,动态生成。


场景2:动画效果

SCSS

@keyframes slideIn {
  from { transform: translateX(-100%); }
  to { transform: translateX(0); }
}

.slide-in { animation: slideIn 0.3s; }

Styled Components

const SlideIn = styled.div`
  animation: ${props => props.duration || '0.3s'} slideIn;
  
  @keyframes slideIn {
    from { transform: translateX(-${props => props.distance || '100%'}); }
    to { transform: translateX(0); }
  }
`

<SlideIn duration="0.5s" distance="200px">

优势: 动画参数可以动态配置。


场景3:复杂条件样式

SCSS

// 需要写很多类
.button { }
.button-primary { }
.button-primary-large { }
.button-primary-large-disabled { }
.button-danger { }
.button-danger-large { }
// ... 组合爆炸

Styled Components

const Button = styled.button`
  padding: ${props => props.size === 'large' ? '20px' : '10px'};
  background: ${props => props.variant === 'primary' ? '#0769fb' : '#dc3545'};
  opacity: ${props => props.disabled ? 0.5 : 1};
  cursor: ${props => props.disabled ? 'not-allowed' : 'pointer'};
`

// 任意组合,无需预定义
<Button variant="primary" size="large" disabled={false}>
<Button variant="danger" size="small" disabled={true}>

优势: 无需预定义所有组合,动态生成。


⚖️ 性能对比

SCSS

  • 编译时处理:编译后就是普通 CSS
  • 运行时性能:零开销
  • 体积:只包含使用的样式

Styled Components

  • ⚠️ 运行时处理:需要 JavaScript 运行时生成样式
  • ⚠️ 运行时开销:很小,但存在
  • ⚠️ 体积:需要引入库(约 15KB gzipped)

注意: 对于大多数应用,Styled Components 的性能开销可以忽略不计。


🎯 结论

Styled Components 是功能最强大的方案

原因:

  1. 动态样式:SCSS 无法实现
  2. 主题系统:内置支持,SCSS 需要手动实现
  3. 组件绑定:自动作用域隔离
  4. 条件样式:JavaScript 逻辑,更灵活
  5. TypeScript:完美支持

SCSS 的优势

  1. 性能:编译时处理,运行时零开销
  2. 简单:学习成本低
  3. 成熟:生态完善

推荐使用场景

使用 Styled Components 当你需要:

  • ✅ 动态样式(根据 props/state)
  • ✅ 主题切换功能
  • ✅ 复杂的条件样式
  • ✅ TypeScript 项目

使用 SCSS 当你需要:

  • ✅ 静态样式
  • ✅ 最佳性能
  • ✅ 简单项目
  • ✅ 不需要动态样式

📦 快速开始

安装

npm install styled-components

基础使用

import styled from 'styled-components'

const Container = styled.div`
  background-color: ${props => props.bgColor || '#0769fb'};
  padding: 16px;
`

function App() {
  return <Container bgColor="#28a745">内容</Container>
}

📚 总结

Styled Components 比 SCSS 功能更强大,主要体现在:

  • ✅ 动态样式(SCSS 无法实现)
  • ✅ 主题系统(内置支持)
  • ✅ 组件绑定(自动隔离)
  • ✅ 条件样式(JavaScript 逻辑)
  • ✅ TypeScript 完美支持

但 SCSS 在性能上更优(编译时处理,零运行时开销)。

选择建议:

  • 需要动态样式 → Styled Components
  • 只需要静态样式 → SCSS