Frontend Academy · 课时

CSS-in-JS:Styled-components 与 Emotion

使用 styled-components 将组件样式编写为带标签的模板字面量,或使用 Emotion 的 css 属性,并利用属性实现动态样式。

第 3 / 4 课13 个步骤

CSS-in-JS:Styled-components 与 Emotion 是 CoddyKit 上的免费 Frontend Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Frontend Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Frontend Academy 课程共包含 4 节课。

什么是 CSS-in-JS

CSS-in-JS 将组件样式直接写在 JavaScript/TypeScript 中。样式与组件放在一起,支持使用 props 中的动态值,并且会自动限制作用域。最流行的两个库是 styled-components 和 Emotion。

styled-components 基础

使用带标签的模板字面量定义样式化组件。结果是一个 React 组件,它会渲染应用了这些样式的 HTML 元素。

import styled from 'styled-components';

const Button = styled.button`
  background: ${props => props.primary ? '#6366f1' : 'white'};
  color: ${props => props.primary ? 'white' : '#6366f1'};
  padding: 8px 16px;
  border: 2px solid #6366f1;
  border-radius: 4px;
  cursor: pointer;

  &:hover {
    opacity: 0.9;
  }
`;

<Button primary>Primary</Button>
<Button>Outline</Button>

Emotion——css 属性

Emotion 的 css 属性可以为任意 JSX 元素应用样式。它需要 @emotion/react pragma 或 Babel 预设。

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

function Card({ featured }: { featured?: boolean }) {
  return (
    <div css={css`
      padding: 16px;
      border-radius: 8px;
      border: ${featured ? '2px solid #6366f1' : '1px solid #e2e8f0'};
    `}>
      Content
    </div>
  );
}

根据 props 生成动态样式

这两个库都可以读取 props 来计算样式。这是它们相较于静态 CSS 的主要优势——不需要切换类名。

使用 ThemeProvider 设置主题

styled-components 和 Emotion 都支持 ThemeProvider,它会将主题值注入所有样式化组件。

import { ThemeProvider } from 'styled-components';

const theme = { colors: { primary: '#6366f1', bg: '#f7fafc' }, space: { sm: 8, md: 16 } };

<ThemeProvider theme={theme}>
  <App />
</ThemeProvider>

// Access in styled component:
const Card = styled.div`
  background: ${props => props.theme.colors.bg};
  padding: ${props => props.theme.space.md}px;
`;

扩展样式化组件

扩展现有的样式化组件,即可创建变体,而无需重复样式。

const Button = styled.button`
  padding: 8px 16px;
  border-radius: 4px;
`;

const DangerButton = styled(Button)`
  background: #e53e3e;
  color: white;
`;

全局样式

对于 body 样式和重置样式等全局 CSS,请使用 createGlobalStyle(styled-components)或 Global(Emotion)。

import { createGlobalStyle } from 'styled-components';

const GlobalStyle = createGlobalStyle`
  *, *::before, *::after { box-sizing: border-box; }
  body { margin: 0; font-family: system-ui; }
`;

<><GlobalStyle /><App /></>

CSS-in-JS 的运行时开销

CSS-in-JS 库会通过 JavaScript 在运行时注入样式。这会增加解析和注入样式所需的 CPU 开销,也会增大 JavaScript 包的体积。零运行时替代方案(vanilla-extract、linaria)会在构建时生成静态 CSS。

零运行时替代方案

vanilla-extract:使用 TypeScript 编写样式,并编译为静态 CSS。linaria:将 CSS-in-JS 语法编译为 CSS 模块。两者都能提供 CSS-in-JS 的使用体验,同时不产生运行时开销。

使用 styled-components 编写 TypeScript

定义 ThemeType,并扩展 styled-components 中的 DefaultTheme 接口,即可获得完全类型化的主题。

import 'styled-components';
import { theme } from './theme';

declare module 'styled-components' {
  export interface DefaultTheme extends typeof theme {}
}

何时选择 CSS-in-JS

CSS-in-JS 非常适合以下场景:由运行时 JavaScript 值驱动的动态样式、强烈需要主题功能的设计系统,以及偏好以 JS 为主工作流的团队。对于非性能关键型界面,其运行时开销通常可以接受。

快速检查

与静态 CSS 方案相比,运行时 CSS-in-JS 库的主要权衡是什么?

回顾:CSS-in-JS

styled-components:使用带标签的模板字面量,渲染样式化的 React 元素。Emotion:使用 css 属性或 styled API。根据 props 生成动态样式,从而无需切换类名。ThemeProvider 注入主题值。使用 createGlobalStyle 创建全局 CSS。主要权衡是运行时开销。零运行时替代方案:vanilla-extract、linaria。

免费开始

用 AI 导师学习 HTML — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
41
课程
163

常见问题解答

「CSS-in-JS:Styled-components 与 Emotion」课时是免费的吗?

是的 — 「CSS-in-JS:Styled-components 与 Emotion」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Frontend Academy 课程的其余内容,请升级到 CoddyKit PRO。 Frontend Academy 课程共包含 4 节课。

「CSS-in-JS:Styled-components 与 Emotion」这节课中我会学到什么?

使用 styled-components 将组件样式编写为带标签的模板字面量,或使用 Emotion 的 css 属性,并利用属性实现动态样式。 你通过在浏览器中直接运行的动手代码来练习 Frontend Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Frontend Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Frontend Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「CSS-in-JS:Styled-components 与 Emotion」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Frontend Academy 课中编写并运行代码吗?

能。每节 Frontend Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. BEM 方法论:块、元素与修饰符
  2. CSS Modules:作用域类名
  3. CSS-in-JS:Styled-components 与 Emotion
  4. Tailwind CSS:实用优先方法
← 返回 Frontend Academy