1. 行内样式:最熟悉的陌生人
function Button() {
return (
<button
style={{
backgroundColor: "#3b82f6",
color: "#fff",
padding: "8px 16px",
border: "none",
borderRadius: "4px",
cursor: "pointer",
}}
>
点我
</button>
);
}
心跳时刻:为什么 background-color 要写成 backgroundColor?
答:因为 style 接收的是 JS 对象,CSS 属性必须转为驼峰命名。
踩坑:
当需要伪类(hover)或媒体查询时,行内样式直接 GG。此时需要...
2. 普通 CSS 文件:最经典的方案
/* Button.module.css */
.btn {
background-color: #3b82f6;
color: #fff;
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;
}
.btn:hover {
background-color: #2563eb;
transform: translateY(-1px);
}
import styles from "./Button.module.css";
function Button() {
return <button className={styles.btn}>点我</button>;
}
心跳时刻:
.module.css 是 CSS Modules 的写法,React 脚手架会自动把类名哈希化,避免全局污染。
(如果你用 Vite,记得在 vite.config.js 里开启 css.modules)
3. CSS-in-JS:当样式变成组件
这里用 styled-components 举例:
npm install styled-components
import styled from "styled-components";
const Button = styled.button`
background-color: #3b82f6;
color: #fff;
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;
&:hover {
background-color: #2563eb;
transform: translateY(-1px);
}
/* 动态 props */
${(props) =>
props.$primary &&
`
background-color: #ec4899;
&:hover {
background-color: #db2777;
}
`}
`;
function App() {
return (
<>
<Button>普通按钮</Button>
<Button $primary>主要按钮</Button>
</>
);
}
心跳时刻:
$primary 的 $ 前缀是为了避免把 props 透传到 DOM 节点(React 会报警告)。
4. 实战对比:一个卡片组件的三种实现
| 方案 | 代码量 | 可维护性 | 动态样式 | SSR 支持 | 适合场景 |
|---|---|---|---|---|---|
| 行内样式 | 少 | 差 | ✅ | ✅ | 快速原型、简单组件 |
| CSS Modules | 中 | 好 | ❌ | ✅ | 常规业务、团队协作 |
| styled-components | 多 | 极好 | ✅ | ✅ | 复杂主题、设计系统 |
5. 我的选择法则
- MVP 阶段:行内样式 + 一个全局
index.css,最快上线。 - 团队协作:CSS Modules + clsx 处理条件类名。
- 设计系统:styled-components + styled-system 做主题令牌。
6. 加餐:TailwindCSS 的另一种哲学
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Tailwind按钮
</button>
心跳时刻:
Tailwind 的本质是「原子化 CSS 库」,不是 CSS-in-JS。
如果你讨厌写样式,但又想保持可控,可以试试它。
附录:常见报错速查表
| 错误信息 | 原因 | 解决 |
|---|---|---|
Warning: Received 'true' for non-boolean attribute 'primary' | styled-components 的 props 没加 $ 前缀 | 改成 $primary |
Unknown property 'class'... | 写成了 class 而不是 className | 改! |
Cannot find module './Button.module.css' | 没安装 CSS Modules 支持 | 检查 webpack/vite 配置 |
下一篇预告:《从 JSX 的花括号到列表 key 的 5 个高频疑问》
点赞超过 50 我就熬夜写!