CSS Modules 与 CSS-in-JS

两种 CSS 作用域方案的对比与使用

问题

CSS Modules 和 CSS-in-JS 分别是什么?它们如何解决样式冲突问题?

解答

CSS Modules

CSS Modules 是一种 CSS 文件的模块化方案,通过构建工具将类名转换为唯一标识符,实现样式隔离。

/* Button.module.css */
.button {
  padding: 8px 16px;
  border-radius: 4px;
}

.primary {
  background: #1890ff;
  color: white;
}
// Button.jsx
import styles from './Button.module.css';

function Button({ children, primary }) {
  return (
    <button className={`${styles.button} ${primary ? styles.primary : ''}`}>
      {children}
    </button>
  );
}

// 编译后的类名类似:Button_button_x7d2s Button_primary_k3j1f

CSS-in-JS

CSS-in-JS 是在 JavaScript 中编写样式的方案,常见库有 styled-components、Emotion 等。

// 使用 styled-components
import styled from 'styled-components';

// 创建带样式的组件
const Button = styled.button`
  padding: 8px 16px;
  border-radius: 4px;
  background: ${props => props.primary ? '#1890ff' : '#fff'};
  color: ${props => props.primary ? '#fff' : '#333'};
  
  &:hover {
    opacity: 0.8;
  }
`;

// 使用
function App() {
  return (
    <div>
      <Button>默认按钮</Button>
      <Button primary>主要按钮</Button>
    </div>
  );
}
// 使用 Emotion
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';

const buttonStyle = css`
  padding: 8px 16px;
  border-radius: 4px;
`;

const primaryStyle = css`
  background: #1890ff;
  color: white;
`;

function Button({ children, primary }) {
  return (
    <button css={[buttonStyle, primary && primaryStyle]}>
      {children}
    </button>
  );
}

对比

特性CSS ModulesCSS-in-JS
样式位置独立 CSS 文件JS 文件中
动态样式需要条件类名原生支持 props
运行时开销有(解析和注入)
服务端渲染简单需要额外配置
学习成本中等
类型支持需要额外配置天然支持

实际选择建议

// CSS Modules 适合:静态样式为主的项目
// styles.module.css
.card {
  border: 1px solid #eee;
}
.card.active {
  border-color: #1890ff;
}

// CSS-in-JS 适合:需要大量动态样式的场景
const Card = styled.div`
  border: 1px solid ${props => props.active ? '#1890ff' : '#eee'};
  transform: scale(${props => props.active ? 1.02 : 1});
  transition: all 0.2s;
`;

关键点

  • CSS Modules 通过编译时转换类名实现隔离,零运行时开销
  • CSS-in-JS 在运行时生成样式,支持基于 props 的动态样式
  • CSS Modules 保持 CSS 和 JS 分离,更接近传统开发方式
  • CSS-in-JS 样式与组件共存,删除组件时样式自动移除
  • 性能敏感场景优先 CSS Modules,交互复杂场景可选 CSS-in-JS