第一个组件 #
一、创建第一个样式组件 #
1.1 最简单的示例 #
jsx
import styled from 'styled-components';
const Title = styled.h1`
font-size: 24px;
color: #333;
`;
function App() {
return <Title>Hello Styled Components</Title>;
}
1.2 渲染结果 #
html
<h1 class="sc-aXZVg iZNUXn">Hello Styled Components</h1>
自动注入的样式:
html
<style data-styled="active">
.sc-aXZVg{font-size:24px;color:#333;}
</style>
二、styled 方法详解 #
2.1 基本语法 #
jsx
const Component = styled.htmlTag`
css styles
`;
2.2 支持的 HTML 元素 #
jsx
const Container = styled.div`...`;
const Button = styled.button`...`;
const Input = styled.input`...`;
const Link = styled.a`...`;
const Image = styled.img`...`;
const Paragraph = styled.p`...`;
const Span = styled.span`...`;
const Header = styled.header`...`;
const Footer = styled.footer`...`;
const Section = styled.section`...`;
const Article = styled.article`...`;
const Nav = styled.nav`...`;
const Ul = styled.ul`...`;
const Li = styled.li`...`;
const H1 = styled.h1`...`;
const H2 = styled.h2`...`;
const H3 = styled.h3`...`;
2.3 字符串形式 #
jsx
const Button = styled('button')`
padding: 10px 20px;
background: blue;
color: white;
`;
const Link = styled('a')`
text-decoration: none;
color: inherit;
`;
三、完整组件示例 #
3.1 按钮组件 #
jsx
import styled from 'styled-components';
const Button = styled.button`
display: inline-flex;
align-items: center;
justify-content: center;
padding: 12px 24px;
font-size: 16px;
font-weight: 600;
line-height: 1;
text-decoration: none;
white-space: nowrap;
cursor: pointer;
border: none;
border-radius: 8px;
transition: all 0.2s ease-in-out;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
box-shadow: 0 4px 6px rgba(102, 126, 234, 0.3);
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(102, 126, 234, 0.4);
}
&:active {
transform: translateY(0);
box-shadow: 0 2px 4px rgba(102, 126, 234, 0.3);
}
&:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
`;
function App() {
return (
<div>
<Button>Click Me</Button>
<Button disabled>Disabled</Button>
</div>
);
}
3.2 卡片组件 #
jsx
import styled from 'styled-components';
const Card = styled.div`
background: white;
border-radius: 16px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
padding: 24px;
max-width: 400px;
transition: transform 0.3s ease, box-shadow 0.3s ease;
&:hover {
transform: translateY(-8px);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
}
`;
const CardTitle = styled.h2`
font-size: 24px;
font-weight: 700;
color: #1a1a2e;
margin: 0 0 12px 0;
`;
const CardDescription = styled.p`
font-size: 16px;
line-height: 1.6;
color: #666;
margin: 0;
`;
function App() {
return (
<Card>
<CardTitle>Card Title</CardTitle>
<CardDescription>
This is a beautiful card component with hover effects.
</CardDescription>
</Card>
);
}
3.3 输入框组件 #
jsx
import styled from 'styled-components';
const InputGroup = styled.div`
display: flex;
flex-direction: column;
gap: 8px;
`;
const Label = styled.label`
font-size: 14px;
font-weight: 600;
color: #333;
`;
const Input = styled.input`
padding: 12px 16px;
font-size: 16px;
border: 2px solid #e0e0e0;
border-radius: 8px;
outline: none;
transition: border-color 0.2s, box-shadow 0.2s;
&:focus {
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.2);
}
&::placeholder {
color: #aaa;
}
`;
function App() {
return (
<InputGroup>
<Label htmlFor="email">Email Address</Label>
<Input
id="email"
type="email"
placeholder="Enter your email"
/>
</InputGroup>
);
}
四、组件组合 #
4.1 组合多个样式组件 #
jsx
import styled from 'styled-components';
const Container = styled.div`
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
`;
const Header = styled.header`
text-align: center;
margin-bottom: 40px;
`;
const Title = styled.h1`
font-size: 48px;
font-weight: 800;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin: 0;
`;
const Subtitle = styled.p`
font-size: 18px;
color: #666;
margin: 16px 0 0 0;
`;
const Grid = styled.div`
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 24px;
`;
const Card = styled.div`
background: white;
border-radius: 16px;
padding: 24px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
`;
function App() {
return (
<Container>
<Header>
<Title>My App</Title>
<Subtitle>Build beautiful interfaces with Styled Components</Subtitle>
</Header>
<Grid>
<Card>Card 1</Card>
<Card>Card 2</Card>
<Card>Card 3</Card>
</Grid>
</Container>
);
}
4.2 布局组件 #
jsx
import styled from 'styled-components';
const Flex = styled.div`
display: flex;
flex-direction: ${props => props.direction || 'row'};
align-items: ${props => props.align || 'center'};
justify-content: ${props => props.justify || 'flex-start'};
gap: ${props => props.gap || '16px'};
`;
const Box = styled.div`
padding: ${props => props.p || '16px'};
margin: ${props => props.m || '0'};
background: ${props => props.bg || 'transparent'};
border-radius: ${props => props.radius || '8px'};
`;
function App() {
return (
<Flex direction="column" gap="24px">
<Flex justify="space-between">
<Box bg="#f0f0f0" p="20px">Left</Box>
<Box bg="#e0e0e0" p="20px">Right</Box>
</Flex>
<Box bg="#f5f5f5" p="24px" radius="12px">
Content Area
</Box>
</Flex>
);
}
五、样式继承 #
5.1 继承 HTML 元素样式 #
jsx
import styled from 'styled-components';
const Button = styled.button`
padding: 12px 24px;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
border: none;
transition: all 0.2s;
`;
const PrimaryButton = styled(Button)`
background: #667eea;
color: white;
&:hover {
background: #5a6fd6;
}
`;
const SecondaryButton = styled(Button)`
background: transparent;
border: 2px solid #667eea;
color: #667eea;
&:hover {
background: #667eea;
color: white;
}
`;
function App() {
return (
<div>
<PrimaryButton>Primary</PrimaryButton>
<SecondaryButton>Secondary</SecondaryButton>
</div>
);
}
5.2 继承第三方组件 #
jsx
import styled from 'styled-components';
import { Link } from 'react-router-dom';
const StyledLink = styled(Link)`
text-decoration: none;
color: #667eea;
font-weight: 600;
padding: 8px 16px;
border-radius: 4px;
transition: background 0.2s;
&:hover {
background: rgba(102, 126, 234, 0.1);
}
`;
function Navigation() {
return (
<nav>
<StyledLink to="/">Home</StyledLink>
<StyledLink to="/about">About</StyledLink>
<StyledLink to="/contact">Contact</StyledLink>
</nav>
);
}
六、嵌套选择器 #
6.1 基本嵌套 #
jsx
import styled from 'styled-components';
const Card = styled.div`
padding: 24px;
background: white;
border-radius: 12px;
h2 {
font-size: 24px;
margin-bottom: 12px;
}
p {
font-size: 16px;
line-height: 1.6;
color: #666;
}
a {
color: #667eea;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
`;
function App() {
return (
<Card>
<h2>Card Title</h2>
<p>This is a paragraph with a <a href="#">link</a>.</p>
</Card>
);
}
6.2 伪类和伪元素 #
jsx
import styled from 'styled-components';
const Input = styled.input`
padding: 12px 16px;
border: 2px solid #e0e0e0;
border-radius: 8px;
outline: none;
&:focus {
border-color: #667eea;
}
&:hover:not(:focus) {
border-color: #c0c0c0;
}
&::placeholder {
color: #aaa;
font-style: italic;
}
&:disabled {
background: #f5f5f5;
cursor: not-allowed;
}
`;
const ListItem = styled.li`
padding: 12px;
border-bottom: 1px solid #eee;
&:first-child {
border-top: 1px solid #eee;
}
&:last-child {
border-bottom: none;
}
&:nth-child(even) {
background: #fafafa;
}
`;
6.3 子代选择器 #
jsx
import styled from 'styled-components';
const Menu = styled.nav`
display: flex;
gap: 8px;
> a {
padding: 12px 20px;
color: #333;
text-decoration: none;
border-radius: 8px;
transition: background 0.2s;
&:hover {
background: #f0f0f0;
}
}
> button {
padding: 12px 20px;
background: #667eea;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
}
`;
function App() {
return (
<Menu>
<a href="/">Home</a>
<a href="/about">About</a>
<button>Sign Up</button>
</Menu>
);
}
七、完整示例:用户卡片 #
jsx
import styled from 'styled-components';
const UserCard = styled.div`
display: flex;
align-items: center;
gap: 16px;
padding: 20px;
background: white;
border-radius: 16px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
max-width: 400px;
transition: transform 0.3s ease, box-shadow 0.3s ease;
&:hover {
transform: translateY(-4px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}
`;
const Avatar = styled.img`
width: 64px;
height: 64px;
border-radius: 50%;
object-fit: cover;
border: 3px solid #667eea;
`;
const UserInfo = styled.div`
flex: 1;
`;
const UserName = styled.h3`
font-size: 18px;
font-weight: 700;
color: #1a1a2e;
margin: 0 0 4px 0;
`;
const UserEmail = styled.p`
font-size: 14px;
color: #666;
margin: 0;
`;
const StatusBadge = styled.span`
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 12px;
font-size: 12px;
font-weight: 600;
border-radius: 20px;
background: ${props => props.online ? '#e6f7ed' : '#fff3e0'};
color: ${props => props.online ? '#00a854' : '#fa8c16'};
&::before {
content: '';
width: 8px;
height: 8px;
border-radius: 50%;
background: ${props => props.online ? '#00a854' : '#fa8c16'};
}
`;
function App() {
return (
<UserCard>
<Avatar src="https://i.pravatar.cc/150?img=1" alt="User" />
<UserInfo>
<UserName>John Doe</UserName>
<UserEmail>john@example.com</UserEmail>
</UserInfo>
<StatusBadge online>Online</StatusBadge>
</UserCard>
);
}
八、调试技巧 #
8.1 使用 displayName #
配置 Babel 插件后,类名会包含组件名:
html
<div class="UserCard__UserCard-sc-aXZVg iZNUXn">
...
</div>
8.2 React DevTools #
在 React DevTools 中可以看到样式组件的名称:
text
<UserCard>
<Avatar>
<UserInfo>
<UserName>
<UserEmail>
</UserInfo>
<StatusBadge>
</UserCard>
8.3 检查生成的样式 #
在浏览器开发者工具中查看 <style> 标签:
html
<style data-styled="active" data-styled-version="6.0.0">
.UserCard__UserCard-sc-aXZVg{display:flex;align-items:center;...}
</style>
九、总结 #
创建样式组件的关键点:
| 要点 | 说明 |
|---|---|
| styled 方法 | styled.tag 或 styled(Tag) |
| 模板字面量 | 使用反引号编写 CSS |
| 自动类名 | 无需手动管理类名 |
| 嵌套选择器 | 支持 SCSS 风格嵌套 |
| 继承 | 使用 styled(Component) 继承 |
下一步:学习 基础语法 了解更多样式定义方式。
最后更新:2026-03-28