第一个组件 #

一、创建第一个样式组件 #

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.tagstyled(Tag)
模板字面量 使用反引号编写 CSS
自动类名 无需手动管理类名
嵌套选择器 支持 SCSS 风格嵌套
继承 使用 styled(Component) 继承

下一步:学习 基础语法 了解更多样式定义方式。

最后更新:2026-03-28