基础语法 #

一、样式定义方式 #

1.1 模板字面量语法 #

Styled Components 使用 ES6 模板字面量定义样式:

jsx
import styled from 'styled-components';

const Button = styled.button`
  padding: 12px 24px;
  font-size: 16px;
  color: white;
  background: #667eea;
  border: none;
  border-radius: 8px;
  cursor: pointer;
`;

1.2 样式对象语法 #

也可以使用 JavaScript 对象定义样式:

jsx
const Button = styled.button({
  padding: '12px 24px',
  fontSize: '16px',
  color: 'white',
  background: '#667eea',
  border: 'none',
  borderRadius: '8px',
  cursor: 'pointer',
});

1.3 混合语法 #

模板字面量中可以嵌入对象:

jsx
const baseStyles = {
  padding: '12px 24px',
  borderRadius: '8px',
};

const Button = styled.button`
  ${baseStyles}
  background: #667eea;
  color: white;
`;

二、CSS 属性命名 #

2.1 驼峰命名 vs 短横线命名 #

jsx
const Card = styled.div`
  background-color: #fff;
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
`;

const Card = styled.div({
  backgroundColor: '#fff',
  borderRadius: '12px',
  boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)',
});

2.2 供应商前缀 #

Styled Components 自动添加浏览器前缀:

jsx
const FlexContainer = styled.div`
  display: flex;
  align-items: center;
  justify-content: center;
`;

编译后:

css
.FlexContainer {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
}

三、插值表达式 #

3.1 基本插值 #

jsx
const primaryColor = '#667eea';

const Button = styled.button`
  background: ${primaryColor};
  color: white;
`;

3.2 函数插值 #

jsx
const getColor = (variant) => {
  switch (variant) {
    case 'primary': return '#667eea';
    case 'success': return '#52c41a';
    case 'danger': return '#ff4d4f';
    default: return '#667eea';
  }
};

const Button = styled.button`
  background: ${props => getColor(props.variant)};
  color: white;
`;

function App() {
  return (
    <>
      <Button variant="primary">Primary</Button>
      <Button variant="success">Success</Button>
      <Button variant="danger">Danger</Button>
    </>
  );
}

3.3 复杂表达式 #

jsx
const Button = styled.button`
  padding: ${props => {
    switch (props.size) {
      case 'small': return '8px 16px';
      case 'large': return '16px 32px';
      default: return '12px 24px';
    }
  }};
  
  font-size: ${props => props.size === 'large' ? '18px' : '16px'};
  
  background: ${props => props.disabled ? '#ccc' : props.primary ? '#667eea' : '#fff'};
  color: ${props => props.disabled ? '#999' : props.primary ? '#fff' : '#667eea'};
  border: 2px solid ${props => props.primary ? '#667eea' : 'transparent'};
  
  cursor: ${props => props.disabled ? 'not-allowed' : 'pointer'};
  opacity: ${props => props.disabled ? 0.6 : 1};
`;

function App() {
  return (
    <>
      <Button primary>Primary Button</Button>
      <Button size="large">Large Button</Button>
      <Button disabled>Disabled Button</Button>
    </>
  );
}

四、嵌套选择器 #

4.1 伪类选择器 #

jsx
const Button = styled.button`
  background: #667eea;
  color: white;
  transition: all 0.2s;

  &:hover {
    background: #5a6fd6;
    transform: translateY(-2px);
  }

  &:active {
    transform: translateY(0);
  }

  &:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.3);
  }

  &:disabled {
    background: #ccc;
    cursor: not-allowed;
    transform: none;
  }
`;

4.2 伪元素选择器 #

jsx
const Input = styled.input`
  padding: 12px 16px;
  border: 2px solid #e0e0e0;
  border-radius: 8px;

  &::placeholder {
    color: #aaa;
    font-style: italic;
  }

  &::-webkit-input-placeholder {
    color: #aaa;
  }

  &::-moz-placeholder {
    color: #aaa;
  }
`;

const Tooltip = styled.span`
  position: relative;

  &::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    padding: 8px 12px;
    background: #333;
    color: white;
    font-size: 12px;
    border-radius: 4px;
    white-space: nowrap;
    opacity: 0;
    visibility: hidden;
    transition: all 0.2s;
  }

  &:hover::after {
    opacity: 1;
    visibility: visible;
  }
`;

4.3 后代选择器 #

jsx
const Card = styled.div`
  padding: 24px;
  background: white;
  border-radius: 12px;

  h2 {
    font-size: 24px;
    margin-bottom: 12px;
  }

  p {
    color: #666;
    line-height: 1.6;
  }

  a {
    color: #667eea;
    text-decoration: none;

    &:hover {
      text-decoration: underline;
    }
  }

  .highlight {
    background: #fff3cd;
    padding: 2px 4px;
    border-radius: 4px;
  }
`;

4.4 子代选择器 #

jsx
const List = styled.ul`
  list-style: none;
  padding: 0;
  margin: 0;

  > li {
    padding: 12px;
    border-bottom: 1px solid #eee;

    &:last-child {
      border-bottom: none;
    }
  }

  > li > a {
    color: #333;
    text-decoration: none;
  }
`;

4.5 相邻兄弟选择器 #

jsx
const Form = styled.form`
  label {
    display: block;
    margin-bottom: 8px;
    font-weight: 600;
  }

  label + input {
    margin-top: 4px;
  }

  input + span {
    display: block;
    margin-top: 4px;
    font-size: 12px;
    color: #666;
  }
`;

五、属性选择器 #

5.1 基本属性选择器 #

jsx
const Input = styled.input`
  padding: 12px;
  border: 2px solid #e0e0e0;
  border-radius: 8px;

  &[type="text"] {
    background: #fff;
  }

  &[type="email"] {
    background: #f0f7ff;
  }

  &[type="password"] {
    background: #fff5f5;
  }

  &[disabled] {
    background: #f5f5f5;
    cursor: not-allowed;
  }

  &[required] {
    border-color: #ffccc7;
  }
`;

5.2 属性存在选择器 #

jsx
const Link = styled.a`
  color: #667eea;
  text-decoration: none;

  &[target="_blank"]::after {
    content: ' ↗';
    font-size: 0.8em;
  }

  &[download] {
    background: #f0f0f0;
    padding: 4px 8px;
    border-radius: 4px;
  }
`;

六、多选择器 #

6.1 选择器分组 #

jsx
const Input = styled.input`
  padding: 12px;
  border: 2px solid #e0e0e0;

  &:focus,
  &:active {
    border-color: #667eea;
    outline: none;
  }

  &:hover,
  &:focus {
    box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
  }
`;

6.2 多元素选择器 #

jsx
const Article = styled.article`
  h1, h2, h3 {
    color: #1a1a2e;
    margin-top: 24px;
  }

  p, ul, ol {
    line-height: 1.8;
    margin-bottom: 16px;
  }

  code, pre {
    background: #f5f5f5;
    font-family: 'Fira Code', monospace;
  }
`;

七、CSS 变量 #

7.1 定义和使用 CSS 变量 #

jsx
const Card = styled.div`
  --card-padding: 24px;
  --card-radius: 12px;
  --card-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  
  padding: var(--card-padding);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  background: white;

  h2 {
    margin-bottom: calc(var(--card-padding) / 2);
  }
`;

7.2 动态 CSS 变量 #

jsx
const Button = styled.button`
  --button-bg: ${props => props.variant === 'primary' ? '#667eea' : '#fff'};
  --button-color: ${props => props.variant === 'primary' ? '#fff' : '#667eea'};
  
  background: var(--button-bg);
  color: var(--button-color);
  padding: 12px 24px;
  border: 2px solid #667eea;
  border-radius: 8px;
  transition: all 0.2s;

  &:hover {
    filter: brightness(0.9);
  }
`;

八、媒体查询 #

8.1 基本媒体查询 #

jsx
const Container = styled.div`
  padding: 16px;
  max-width: 100%;

  @media (min-width: 768px) {
    padding: 24px;
    max-width: 720px;
    margin: 0 auto;
  }

  @media (min-width: 1024px) {
    padding: 32px;
    max-width: 960px;
  }

  @media (min-width: 1280px) {
    max-width: 1140px;
  }
`;

8.2 嵌套媒体查询 #

jsx
const Grid = styled.div`
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr;

  @media (min-width: 640px) {
    grid-template-columns: repeat(2, 1fr);
  }

  @media (min-width: 1024px) {
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
  }

  @media (min-width: 1280px) {
    grid-template-columns: repeat(4, 1fr);
  }
`;

8.3 媒体查询变量 #

jsx
const breakpoints = {
  sm: '640px',
  md: '768px',
  lg: '1024px',
  xl: '1280px',
};

const Container = styled.div`
  padding: 16px;

  @media (min-width: ${breakpoints.md}) {
    padding: 24px;
  }

  @media (min-width: ${breakpoints.lg}) {
    padding: 32px;
  }
`;

九、计算值 #

9.1 calc() 函数 #

jsx
const Sidebar = styled.aside`
  width: 280px;
  height: calc(100vh - 64px);
  padding: 24px;
  background: #f5f5f5;
`;

const MainContent = styled.main`
  margin-left: 280px;
  padding: 24px;
  min-height: calc(100vh - 64px);
`;

const Input = styled.input`
  width: calc(100% - 48px);
  padding: 12px 24px;
`;

9.2 数学运算 #

jsx
const baseSize = 16;

const Title = styled.h1`
  font-size: ${baseSize * 2}px;
  line-height: ${baseSize * 2.5}px;
  margin-bottom: ${baseSize}px;
`;

const Paragraph = styled.p`
  font-size: ${baseSize}px;
  line-height: ${baseSize * 1.6}px;
  margin-bottom: ${baseSize * 0.75}px;
`;

十、注释 #

10.1 CSS 注释 #

jsx
const Button = styled.button`
  padding: 12px 24px;
  background: #667eea;
  color: white;
  
  transition: all 0.2s;
  
  &:hover {
    background: #5a6fd6;
  }
`;

10.2 组织性注释 #

jsx
const Card = styled.div`
  background: white;
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  
  padding: 24px;
  
  display: flex;
  flex-direction: column;
  gap: 16px;
  
  h2 {
    font-size: 24px;
    margin: 0;
  }
  
  p {
    color: #666;
    line-height: 1.6;
    margin: 0;
  }
  
  a {
    color: #667eea;
    
    &:hover {
      text-decoration: underline;
    }
  }
`;

十一、转义特殊字符 #

11.1 转义美元符号 #

jsx
const Price = styled.span`
  &::before {
    content: '\\00A5';
    margin-right: 4px;
  }
`;

const Dollar = styled.span`
  &::before {
    content: '\\0024';
  }
`;

11.2 使用 Unicode #

jsx
const Icon = styled.span`
  &::before {
    content: '\\1F4A1';
    margin-right: 8px;
  }
`;

const Checkmark = styled.span`
  &::before {
    content: '\\2713';
    color: #52c41a;
    margin-right: 8px;
  }
`;

十二、总结 #

语法要点速查表:

语法 示例
基本样式 styled.button\color: red;``
插值 \${props => props.color}\
伪类 &:hover { ... }
伪元素 &::before { ... }
嵌套 h2 { ... }
子代 > li { ... }
属性 &[disabled] { ... }
媒体查询 @media (min-width: 768px) { ... }
计算 calc(100% - 24px)
CSS 变量 --var: value; color: var(--var);

下一步:学习 Props适配 掌握动态样式技巧。

最后更新:2026-03-28