styled-components 是 React 中最流行、最强大的 CSS-in-JS 方案之一。
下面我会帮你系统梳理一套"快速上手 + 常用实战场景代码"清单,你照着练一遍就能快速掌握 90% 的日常用法。
🧩 一、核心概念理解
✅ 什么是 styled-components?
它让你能在 React 组件中写出这样的代码:
css
import styled from "styled-components";
const Button = styled.button`
background: #007bff;
color: white;
padding: 8px 16px;
border-radius: 8px;
border: none;
&:hover {
background: #0056b3;
}
`;
export default function App() {
return <Button>点击我</Button>;
}
👉 样式写在组件里(支持所有 CSS 语法),自动生成唯一 className,避免命名冲突。
🚀 二、快速入门步骤
1️⃣ 安装
npm install styled-components
(TS 项目建议再装)
css
npm install --save-dev @types/styled-components
2️⃣ 创建样式组件
javascript
import styled from "styled-components";
const Container = styled.div`
max-width: 1200px;
margin: 0 auto;
`;
export default function App() {
return <Container>Hello styled-components</Container>;
}
🧱 三、开发中常用实战场景
🧠 1. 动态样式(根据 props 改变样式)
css
const Button = styled.button<{ $primary?: boolean }>`
background: ${({ $primary }) => ($primary ? "#007bff" : "#ccc")};
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
`;
export default function App() {
return (
<>
<Button $primary>主要按钮</Button>
<Button>次要按钮</Button>
</>
);
}
✅ 关键:props 前加
$可避免 TS 报错并防止传到 DOM。
🎨 2. 主题(ThemeProvider)
全局定义主题(颜色、字号等):
javascript
import styled, { ThemeProvider } from "styled-components";
const theme = {
colors: {
primary: "#007bff",
secondary: "#6c757d",
},
};
const Title = styled.h1`
color: ${({ theme }) => theme.colors.primary};
`;
export default function App() {
return (
<ThemeProvider theme={theme}>
<Title>这是标题</Title>
</ThemeProvider>
);
}
🧩 3. 样式继承(继承另一个 styled 组件)
ini
const Button = styled.button`
background: gray;
color: white;
`;
const PrimaryButton = styled(Button)`
background: blue;
`;
📦 4. 嵌套选择器 & 状态样式
css
const Card = styled.div`
padding: 16px;
border: 1px solid #eee;
h3 {
margin-bottom: 8px;
}
&:hover {
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
`;
🧮 5. 响应式写法(内联媒体查询)
css
const Box = styled.div`
width: 100%;
background: lightgray;
@media (min-width: 768px) {
background: pink;
}
`;
🪄 6. 动画(使用 keyframes)
css
import styled, { keyframes } from "styled-components";
const fadeIn = keyframes`
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
`;
const AnimatedDiv = styled.div`
animation: ${fadeIn} 0.5s ease-in-out;
`;
🧩 7. 全局样式(GlobalStyle)
javascript
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: #f8f9fa;
}
`;
export default function App() {
return (
<>
<GlobalStyle />
<div>Hello World</div>
</>
);
}
⚙️ 8. 组件之间复用 mixin(常用技巧)
javascript
import { css } from "styled-components";
const flexCenter = css`
display: flex;
justify-content: center;
align-items: center;
`;
const Box = styled.div`
${flexCenter};
height: 100px;
background: #eee;
`;
🧱 9. 条件样式组合
ini
const Tag = styled.span<{ $type: "success" | "error" }>`
color: ${({ $type }) => ($type === "success" ? "green" : "red")};
border: 1px solid currentColor;
padding: 4px 8px;
border-radius: 4px;
`;
🧩 10. 动态组件类型(as)
javascript
const Button = styled.button`
background: blue;
color: white;
`;
export default function App() {
return (
<>
<Button>按钮</Button>
<Button as="a" href="#">
链接样式
</Button>
</>
);
}
🧠 四、进阶建议
| 场景 | 推荐方式 |
|---|---|
| 全局变量(颜色、间距) | 使用 ThemeProvider |
| 公共样式(布局、按钮) | 定义 mixin 或基础组件 |
| 响应式布局 | 使用 CSS 媒体查询或 styled-system |
| 动态切换主题 | 搭配 React Context + ThemeProvider |
| SSR(Next.js) | 需配置 ServerStyleSheet |
✅ 五、快速学习路线总结
| 阶段 | 目标 | 学习重点 |
|---|---|---|
| 入门 | 写静态组件 | styled.div / 动态 props |
| 实战 | 页面组件化 | theme、嵌套、动画 |
| 进阶 | 复用与规范 | mixin、全局样式、响应式 |
| 企业实践 | 主题系统 | dark/light 模式、组件库封装 |
antd 组件开发
在 Ant Design 项目中优雅地修改组件样式(尤其是 Table、Form 等复杂组件) ------
是前端开发中最常见、也是最容易"写乱"的部分。
🧩 一、AntD + styled-components 修改样式的推荐策略
AntD 组件结构复杂(如 .ant-table, .ant-form-item 内部嵌套很多层),
直接 styled(组件) 往往不够精准。
👉 推荐的三种层级控制策略如下:
| 优先级 | 场景 | 推荐写法 |
|---|---|---|
| ✅ 1. 外层容器 + class 精准覆盖 | 修改组件内部结构样式 | styled.div 包裹 .ant-xxx |
| ✅ 2. styled(antd组件) | 修改按钮、Input、Card 等简单组件 | styled(Button) |
| ⚙️ 3. 主题/Token 修改 | 全局颜色、边框、字体等统一 | ConfigProvider theme={{ token: {} }} |
🚀 二、实战写法(Table、Form)
🧱 1️⃣ 修改 Table 样式
AntD 的 Table 结构复杂(表头 + 单元格 + 滚动条),推荐使用外层容器 + class 选择器:
css
import styled from "styled-components";
import { Table } from "antd";
const StyledTableWrapper = styled.div`
.ant-table {
border-radius: 8px;
overflow: hidden;
}
.ant-table-thead > tr > th {
background: #fafafa;
font-weight: 600;
}
.ant-table-tbody > tr:hover > td {
background: #f0f7ff;
}
.ant-table-cell {
padding: 12px 16px;
}
`;
export default function Demo() {
const dataSource = [{ key: 1, name: "张三", age: 28 }];
const columns = [ { title: "姓名", dataIndex: "name" }, { title: "年龄", dataIndex: "age" }, ];
return (
<StyledTableWrapper>
<Table dataSource={dataSource} columns={columns} pagination={false} />
</StyledTableWrapper>
);
}
✅ 这种写法最安全,不会影响全局,也能精确控制局部样式。
🧩 2️⃣ 修改 Form 样式
Form 内部同样嵌套 .ant-form-item、.ant-form-item-label、.ant-form-item-control,
用容器 + 局部覆盖最稳定。
css
import styled from "styled-components";
import { Form, Input, Button } from "antd";
const StyledForm = styled(Form)`
max-width: 400px;
margin: 0 auto;
.ant-form-item {
margin-bottom: 20px;
}
.ant-form-item-label > label {
font-weight: 500;
}
.ant-input {
border-radius: 6px;
height: 40px;
}
.ant-btn-primary {
border-radius: 6px;
font-weight: 600;
}
`;
export default function DemoForm() {
return (
<StyledForm layout="vertical">
<Form.Item label="用户名">
<Input placeholder="请输入用户名" />
</Form.Item>
<Form.Item label="密码">
<Input.Password placeholder="请输入密码" />
</Form.Item>
<Form.Item>
<Button type="primary" block>
登录
</Button>
</Form.Item>
</StyledForm>
);
}
✅ 局部容器内重写
.ant-xxx,可实现完整控制而不影响全局。
🧠 三、推荐封装思路
✅ 1. 通用样式容器封装
定义一个全局通用容器组件,例如:
css
// src/components/StyledWrapper.tsx
import styled from "styled-components";
export const StyledWrapper = styled.div`
.ant-btn {
border-radius: 6px;
}
.ant-input {
border-radius: 4px;
}
.ant-table {
border-radius: 8px;
}
`;
使用时只需包裹局部区域:
xml
<StyledWrapper>
<Table ... />
</StyledWrapper>
✅ 适合团队统一风格管理,不污染 AntD 全局样式。
✅ 2. 封装通用组件
例如二次封装一个统一风格的表单:
javascript
import { Form } from "antd";
import styled from "styled-components";
export const StyledForm = styled(Form)`
.ant-form-item {
margin-bottom: 16px;
}
`;
之后你所有的表单都使用
<StyledForm>,统一视觉。
🎨 四、配合主题变量(ThemeProvider + ConfigProvider)
在大多数企业项目中,你可以用双层主题管理:
xml
<ConfigProvider
theme={{
token: {
colorPrimary: "#1677ff",
borderRadius: 8,
},
}}
>
<ThemeProvider theme={{ primary: "#1677ff" }}>
<App />
</ThemeProvider>
</ConfigProvider>
在 styled 里使用:
ini
const Title = styled.h2`
color: ${({ theme }) => theme.primary};
`;
在 AntD 中使用:
ini
<Button type="primary">按钮</Button>
✅ 双主题体系:AntD 控制组件级 token,styled 控制自定义区域。
🧩 五、总结推荐写法清单
| 场景 | 推荐写法 | 说明 |
|---|---|---|
| 修改 AntD 简单组件(Button、Input) | styled(Button) |
简洁直接 |
| 修改复杂组件(Table、Form、Modal) | styled.div + .ant-xxx |
精确安全 |
| 全局视觉定制 | ConfigProvider theme={{ token: {} }} |
官方推荐 |
| 自定义样式变量 | ThemeProvider |
自定义区域样式 |
| 可复用的布局或容器 | 封装 StyledWrapper |
团队统一样式管理 |
⚡ 六、额外技巧(进阶)
✅ 动态主题切换(亮色 / 暗色)
用 React Context + ThemeProvider 切换 theme,同时动态传给 ConfigProvider。
✅ 控制样式作用域
如果需要防止样式"溢出",可以用:
ini
const Wrapper = styled.div.attrs({ className: 'custom-scope' })``;
然后用 .custom-scope .ant-xxx 精准限定。
✅ 防止样式失效
AntD 样式层级高(有时用 inline style),
必要时可以使用 !important,但建议局部使用,不滥用。