第一个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. 选择合适的方式 #
- 使用
cssprop:简单样式、一次性样式 - 使用
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