样式方案
本教程共 50 篇 · 第 12 篇 · 更新于 2026-07-29 · 约 7 分钟阅读
12. 样式方案
本节目标:了解 React 主流样式方案,掌握 className 用法,能根据项目需求选择合适的样式策略。
React 样式的本质
React 不规定你怎么写 CSS。所有方案最终都生成 CSS,区别只在于怎么组织和作用域怎么控制。
// 不管用哪种方案,JSX 里都是这样引用
<div className="card">内容</div>
Note记住是
className不是class。这个坑我踩过不止一次。
方案一:普通 CSS
最直接的方式——写 .css 文件,在组件里 import。
/* Card.css */
.card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
}
.card-title {
font-size: 18px;
font-weight: bold;
}
// Card.jsx
import './Card.css';
function Card({ title, children }) {
return (
<div className="card">
<h2 className="card-title">{title}</h2>
<div>{children}</div>
</div>
);
}
优点:简单、上手快、和传统写网页一样
缺点:全局作用域——class 名可能冲突。你定义一个 .button,我定义一个 .button,后写的覆盖先写的。
Tip小项目或原型阶段用普通 CSS 就够了。项目一大就得上其他方案。
方案二:CSS Modules
CSS Modules 解决全局污染问题。每个 CSS 文件变成模块,类名自动生成唯一哈希。
/* Card.module.css */
.card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
}
.title {
font-size: 18px;
font-weight: bold;
}
// Card.jsx
import styles from './Card.module.css';
function Card({ title, children }) {
return (
<div className={styles.card}>
<h2 className={styles.title}>{title}</h2>
<div>{children}</div>
</div>
);
}
编译后类名会变成 Card_card_x7k9a、Card_title_m3p2q,保证全局唯一。
优点:无冲突、可复用、和普通 CSS 写法一样
缺点:类名不能动态拼接(要用 classnames 库辅助)
NoteVite 原生支持 CSS Modules——文件命名
xxx.module.css即可,不需要额外配置。
方案三:Tailwind CSS
Tailwind 是原子化 CSS框架。不写 CSS 文件,直接在 className 里写工具类:
function Card({ title, children }) {
return (
<div className="border border-gray-200 rounded-lg p-4 shadow-sm">
<h2 className="text-lg font-bold text-gray-800">{title}</h2>
<div className="text-gray-600 mt-2">{children}</div>
</div>
);
}
每个类对应一个 CSS 属性——p-4 是 padding: 1rem,text-lg 是 font-size: 1.125rem。
优点:开发效率高、无需起类名、最终打包只包含用到的样式
缺点:className 很长、需要记类名、HTML 可读性降低
// 极端例子:一个元素的 className 可能很长
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
方案四:CSS-in-JS
CSS-in-JS 是在 JS 里写 CSS。以 styled-components 为例:
import styled from 'styled-components';
const Card = styled.div`
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
`;
const Title = styled.h2`
font-size: 18px;
font-weight: bold;
`;
function MyCard({ title, children }) {
return (
<Card>
<Title>{title}</Title>
<div>{children}</div>
</Card>
);
}
优点:完全隔离、能动态样式、组件化彻底
缺点:运行时开销、调试困难、学习成本高
内联 style 对象
React 支持直接传 style 对象:
function ColoredBox() {
return (
<div style={{
backgroundColor: 'black',
color: 'pink',
padding: '16px',
}}>
内容
</div>
);
}
注意是 {{ 双括号——外层是 JSX 表达式,内层是对象字面量。CSS 属性名用驼峰。
Warning内联样式不要用太多。它不支持伪类(
:hover)、媒体查询、动画。只适合动态计算样式(比如根据状态变化的宽度)。
动态 className
根据条件切换 className 是最常见的需求:
function Button({ variant }) {
return (
<button className={variant === 'primary' ? 'btn-primary' : 'btn-default'}>
按钮
</button>
);
}
多个条件叠加时,手动拼接会很乱。推荐用 classnames 库:
npm install classnames
import cn from 'classnames';
function Button({ variant, disabled, size }) {
return (
<button
className={cn('btn', {
'btn-primary': variant === 'primary',
'btn-danger': variant === 'danger',
'btn-disabled': disabled,
'btn-sm': size === 'small',
'btn-lg': size === 'large',
})}
>
按钮
</button>
);
}
方案怎么选
| 方案 | 适用场景 | 学习成本 |
|---|---|---|
| 普通 CSS | 小项目、原型、学习阶段 | 低 |
| CSS Modules | 中大型项目、需要隔离 | 低 |
| Tailwind CSS | 快速开发、设计系统 | 中 |
| CSS-in-JS | 组件库、动态主题 | 高 |
Tip初学阶段推荐:普通 CSS → CSS Modules。等你有项目经验了,再考虑 Tailwind 或 CSS-in-JS。
实战示例
一个按钮组件,支持多种样式:
// Button.jsx
import styles from './Button.module.css';
import cn from 'classnames';
export default function Button({ variant = 'default', disabled, children }) {
return (
<button
className={cn(
styles.btn,
styles[`btn-${variant}`],
disabled && styles.disabled
)}
disabled={disabled}
>
{children}
</button>
);
}
/* Button.module.css */
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.btn-default {
background: #f0f0f0;
color: #333;
}
.btn-primary {
background: #1890ff;
color: white;
}
.btn-danger {
background: #ff4d4f;
color: white;
}
.disabled {
opacity: 0.5;
cursor: not-allowed;
}
本节小结
- React 不规定样式方案,四种主流:普通 CSS、CSS Modules、Tailwind、CSS-in-JS
- 记住用
className不是class - CSS Modules 解决命名冲突,Vite 原生支持
- 内联
style只适合动态值 - 动态 className 用
classnames库更优雅
到这里,模块一和模块二的内容全部学完了。你已经掌握了 React 的描述 UI 能力——组件、JSX、条件渲染、列表渲染、样式。
下一模块”添加交互”将进入事件处理和状态管理,让你的页面真正动起来。