第一个Emotion应用 #

快速开始 #

让我们创建第一个使用 Emotion 的 React 应用,体验 CSS-in-JS 的魅力。

示例一:使用 css prop #

css prop 是 Emotion 最直接的使用方式,适合快速添加样式:

jsx
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'

function App() {
  return (
    <div
      css={css`
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        min-height: 100vh;
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      `}
    >
      <h1
        css={css`
          color: white;
          font-size: 48px;
          font-weight: bold;
          text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
        `}
      >
        Hello Emotion!
      </h1>
      <p
        css={css`
          color: rgba(255, 255, 255, 0.9);
          font-size: 18px;
          margin-top: 16px;
        `}
      >
        这是我的第一个 Emotion 应用
      </p>
    </div>
  )
}

export default App

示例二:使用对象样式 #

除了模板字符串,还可以使用 JavaScript 对象定义样式:

jsx
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'

const containerStyle = css({
  display: 'flex',
  flexDirection: 'column',
  alignItems: 'center',
  justifyContent: 'center',
  minHeight: '100vh',
  background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
})

const titleStyle = css({
  color: 'white',
  fontSize: '48px',
  fontWeight: 'bold',
  textShadow: '2px 2px 4px rgba(0, 0, 0, 0.3)',
})

function App() {
  return (
    <div css={containerStyle}>
      <h1 css={titleStyle}>Hello Emotion!</h1>
    </div>
  )
}

export default App

示例三:使用 styled API #

styled API 更适合创建可复用的样式组件:

jsx
import styled from '@emotion/styled'

const Container = styled.div`
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
`

const Title = styled.h1`
  color: white;
  font-size: 48px;
  font-weight: bold;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
  
  @media (max-width: 768px) {
    font-size: 32px;
  }
`

const Description = styled.p`
  color: rgba(255, 255, 255, 0.9);
  font-size: 18px;
  margin-top: 16px;
`

function App() {
  return (
    <Container>
      <Title>Hello Emotion!</Title>
      <Description>这是我的第一个 Emotion 应用</Description>
    </Container>
  )
}

export default App

示例四:动态样式 #

Emotion 的强大之处在于可以基于 props 创建动态样式:

jsx
import styled from '@emotion/styled'

const Button = styled.button`
  padding: 12px 24px;
  font-size: 16px;
  font-weight: bold;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s ease;
  
  background-color: ${props => {
    switch (props.variant) {
      case 'primary':
        return '#007bff'
      case 'success':
        return '#28a745'
      case 'danger':
        return '#dc3545'
      default:
        return '#6c757d'
    }
  }};
  
  color: ${props => props.variant === 'warning' ? '#333' : 'white'};
  
  &:hover {
    opacity: 0.9;
    transform: translateY(-2px);
  }
  
  &:active {
    transform: translateY(0);
  }
  
  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
  }
`

function App() {
  return (
    <div style={{ display: 'flex', gap: '12px' }}>
      <Button variant="primary">Primary</Button>
      <Button variant="success">Success</Button>
      <Button variant="danger">Danger</Button>
      <Button>Default</Button>
      <Button disabled>Disabled</Button>
    </div>
  )
}

export default App

示例五:组合样式组件 #

创建一个完整的卡片组件:

jsx
import styled from '@emotion/styled'

const Card = styled.div`
  background: white;
  border-radius: 12px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  max-width: 320px;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
  
  &:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 12px rgba(0, 0, 0, 0.15);
  }
`

const CardImage = styled.img`
  width: 100%;
  height: 180px;
  object-fit: cover;
`

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

const CardTitle = styled.h3`
  margin: 0 0 8px;
  font-size: 18px;
  color: #333;
`

const CardDescription = styled.p`
  margin: 0;
  font-size: 14px;
  color: #666;
  line-height: 1.5;
`

const CardFooter = styled.div`
  padding: 12px 16px;
  border-top: 1px solid #eee;
  display: flex;
  justify-content: space-between;
  align-items: center;
`

const Price = styled.span`
  font-size: 20px;
  font-weight: bold;
  color: #007bff;
`

const BuyButton = styled.button`
  padding: 8px 16px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-weight: bold;
  
  &:hover {
    background: #0056b3;
  }
`

function ProductCard({ image, title, description, price }) {
  return (
    <Card>
      <CardImage src={image} alt={title} />
      <CardContent>
        <CardTitle>{title}</CardTitle>
        <CardDescription>{description}</CardDescription>
      </CardContent>
      <CardFooter>
        <Price>¥{price}</Price>
        <BuyButton>购买</BuyButton>
      </CardFooter>
    </Card>
  )
}

function App() {
  return (
    <div style={{ display: 'flex', gap: '20px', padding: '20px' }}>
      <ProductCard
        image="https://via.placeholder.com/320x180"
        title="商品标题"
        description="这是一个商品描述,介绍商品的特点和优势。"
        price={99.99}
      />
    </div>
  )
}

export default App

样式复用 #

使用 css 函数创建可复用的样式片段:

jsx
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'

const flexCenter = css`
  display: flex;
  align-items: center;
  justify-content: center;
`

const cardShadow = css`
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
`

function App() {
  return (
    <div css={[flexCenter, cardShadow, css`height: 100vh;`]}>
      <p>组合样式示例</p>
    </div>
  )
}

最佳实践 #

1. 选择合适的方式 #

  • 使用 css prop:简单样式、一次性样式
  • 使用 styled:可复用组件、复杂组件

2. 样式命名 #

使用语义化的组件名称:

jsx
const PrimaryButton = styled.button`...`
const CardContainer = styled.div`...`
const NavigationBar = styled.nav`...`

3. 样式组织 #

将样式定义放在组件外部:

jsx
const styles = {
  container: css`...`,
  title: css`...`,
}

function Component() {
  return (
    <div css={styles.container}>
      <h1 css={styles.title}>Title</h1>
    </div>
  )
}

下一步 #

恭喜你完成了第一个 Emotion 应用!继续学习 两种使用方式,深入了解 css prop 和 styled 的区别与选择。

最后更新:2026-03-28