Emotion 入門:3 分でわかるセットアップと最初の一歩

現代の React 開発において、スタイリング手法の選択は開発体験を大きく左右します。CSS Modules、styled-components、そして今回ご紹介する Emotion。これらの中でも、Emotion は特に注目を集めている CSS-in-JS ライブラリです。
「3 分で Emotion を始められるの?」と疑問に思われるかもしれませんが、実際にその通りなのです。Emotion は学習コストが低く、既存のプロジェクトにも段階的に導入できる優れた特徴を持っています。
本記事では、Emotion の基本的な概念から実際のセットアップ、そして最初のコンポーネント作成まで、わずか 3 分で体験できるように構成いたしました。初心者の方でも安心して取り組めるよう、よくあるエラーの対処法も含めて詳しく解説していきます。
背景
CSS-in-JS ライブラリの必要性
現代の Web 開発では、コンポーネントベースの開発が主流となっています。React、Vue、Angular など、多くのフレームワークがこの手法を採用していますね。
しかし、従来の CSS は「グローバルスコープ」という特徴があり、コンポーネントベース開発との相性に課題がありました。
項目 | 従来の CSS | CSS-in-JS |
---|---|---|
スコープ | グローバル | コンポーネント単位 |
動的スタイル | 困難 | 簡単 |
TypeScript 連携 | 限定的 | 完全対応 |
バンドル最適化 | 手動 | 自動 |
従来の CSS の課題と現代的な解決策
従来の CSS 管理で直面する主な課題は以下の通りです:
グローバル名前空間の競合 多くの開発者が経験する問題として、CSS クラス名の競合があります。特に大規模なプロジェクトでは、意図しないスタイルの上書きが発生することがあります。
コンポーネントとスタイルの分離 JSX ファイルと CSS ファイルが別々に管理されることで、コンポーネントの移動や削除時にスタイルが残ってしまう問題も頻繁に発生します。
動的スタイリングの複雑さ props や state に基づいてスタイルを変更する際、従来の CSS では複雑な条件分岐が必要になることがあります。
CSS-in-JS ライブラリは、これらの課題を根本的に解決する現代的なアプローチを提供しています。
課題
スタイリング管理の複雑さ
実際の開発現場では、以下のような問題に直面することがあります:
CSS Modules の場合
typescript// Button.module.css
.button {
background: blue;
color: white;
}
.button--primary {
background: red;
}
// Button.tsx
import styles from './Button.module.css';
const Button = ({ primary, children }) => {
return (
<button
className={`${styles.button} ${primary ? styles['button--primary'] : ''}`}
>
{children}
</button>
);
};
このアプローチでは、クラス名の管理が煩雑になり、動的なスタイリングが困難になります。
コンポーネントベース開発での CSS 管理の問題
React 開発でよく発生する問題の一つが、コンポーネントの再利用性とスタイルの管理です。
よくある問題例
typescript// 問題のあるコード例
const Card = ({ isActive, variant }) => {
// 複雑な条件分岐
const getClassName = () => {
let className = 'card';
if (isActive) className += ' card--active';
if (variant === 'primary')
className += ' card--primary';
if (variant === 'secondary')
className += ' card--secondary';
return className;
};
return <div className={getClassName()}>...</div>;
};
このような実装では、スタイルの管理が複雑になり、バグの原因となることがあります。
解決策
Emotion が提供する機能とメリット
Emotion は、上記の課題を解決するための強力な機能を提供します:
機能 | 説明 | メリット |
---|---|---|
CSS Prop | JSX 内で直接スタイルを記述 | 直感的な書き方 |
Styled Components | スタイル付きコンポーネントの作成 | 再利用性の向上 |
Theme Provider | テーマ機能 | 一貫したデザインシステム |
TypeScript 対応 | 型安全なスタイリング | 開発時のエラー防止 |
主要なメリット
-
自動的なスコープ管理 クラス名の競合を自動的に防ぎ、コンポーネント単位でのスタイル管理が可能です。
-
動的スタイリングの簡素化 props や state に基づいたスタイルの変更が直感的に行えます。
-
優れた開発体験 TypeScript との連携により、スタイルプロパティの補完やエラーチェックが利用できます。
他の CSS-in-JS ライブラリとの比較
現在、主要な CSS-in-JS ライブラリとして以下があります:
ライブラリ | バンドルサイズ | 学習コスト | TypeScript 対応 | 特徴 |
---|---|---|---|---|
Emotion | 小さい | 低い | 優秀 | 柔軟性が高い |
styled-components | 中程度 | 低い | 良好 | 豊富な機能 |
JSS | 大きい | 高い | 良好 | 設定が複雑 |
Linaria | 非常に小さい | 中程度 | 良好 | ゼロランタイム |
Emotion は、特に軽量性と学習コストの低さで優れており、初心者にも取り組みやすいライブラリです。
具体例
環境構築とインストール
それでは、実際に Emotion を使った開発を始めてみましょう。
Step 1: 新しい Next.js プロジェクトの作成
bash# Next.jsプロジェクトを作成
npx create-next-app@latest emotion-tutorial --typescript --tailwind --eslint
# プロジェクトディレクトリに移動
cd emotion-tutorial
Step 2: Emotion のインストール
bash# Emotionのコアパッケージをインストール
yarn add @emotion/react @emotion/styled
# Next.js用の設定パッケージも追加
yarn add @emotion/babel-plugin
Step 3: Next.js での Emotion 設定
Next.js で Emotion を使用するために、.babelrc
ファイルを作成します:
json{
"presets": [
[
"next/babel",
{
"preset-react": {
"runtime": "automatic",
"importSource": "@emotion/react"
}
}
]
],
"plugins": ["@emotion/babel-plugin"]
}
よくあるエラーと解決法
この段階で発生する可能性のあるエラーとその解決法をご紹介します:
bash# エラー例1: babel-plugin-macrosが見つからない
Error: Cannot find module 'babel-plugin-macros'
# 解決法
yarn add babel-plugin-macros --dev
bash# エラー例2: TypeScriptの型エラー
Property 'css' does not exist on type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'
# 解決法: tsconfig.jsonにjsxImportSourceを追加
{
"compilerOptions": {
"jsx": "preserve",
"jsxImportSource": "@emotion/react"
}
}
基本的な使い方(styled component)
Emotion の基本的な使い方を、実際のコンポーネントを作成しながら学んでいきましょう。
最初の Styled Component
typescript// components/Button.tsx
import styled from '@emotion/styled';
// 基本的なボタンコンポーネント
const StyledButton = styled.button`
background: #007bff;
color: white;
border: none;
padding: 12px 24px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
transition: background 0.2s ease;
&:hover {
background: #0056b3;
}
&:active {
transform: translateY(1px);
}
`;
export const Button = ({ children, ...props }) => {
return <StyledButton {...props}>{children}</StyledButton>;
};
この例では、通常のbutton
要素にスタイルを適用したStyledButton
を作成しています。CSS の書き方は従来の CSS とほとんど同じですが、コンポーネント内にスコープが限定されます。
CSS Prop を使った書き方
typescript// components/Card.tsx
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
const cardStyles = css`
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
padding: 20px;
margin: 10px;
transition: transform 0.2s ease;
&:hover {
transform: translateY(-2px);
}
`;
export const Card = ({ children }) => {
return <div css={cardStyles}>{children}</div>;
};
CSS Prop を使用することで、より直感的にスタイルを適用できます。
props を使った動的スタイリング
Emotion の真の力は、props に基づいた動的なスタイリングにあります。
条件付きスタイリング
typescript// components/Alert.tsx
import styled from '@emotion/styled';
// 型定義
interface AlertProps {
variant: 'success' | 'warning' | 'error' | 'info';
children: React.ReactNode;
}
const StyledAlert = styled.div<AlertProps>`
padding: 16px;
border-radius: 4px;
margin: 10px 0;
border-left: 4px solid;
${({ variant }) => {
switch (variant) {
case 'success':
return `
background: #d4edda;
border-color: #28a745;
color: #155724;
`;
case 'warning':
return `
background: #fff3cd;
border-color: #ffc107;
color: #856404;
`;
case 'error':
return `
background: #f8d7da;
border-color: #dc3545;
color: #721c24;
`;
case 'info':
return `
background: #d1ecf1;
border-color: #17a2b8;
color: #0c5460;
`;
default:
return '';
}
}}
`;
export const Alert: React.FC<AlertProps> = ({
variant,
children,
}) => {
return (
<StyledAlert variant={variant}>{children}</StyledAlert>
);
};
使用例
typescript// pages/index.tsx
import { Alert } from '../components/Alert';
export default function Home() {
return (
<div>
<Alert variant='success'>
操作が正常に完了しました!
</Alert>
<Alert variant='error'>
エラーが発生しました。再試行してください。
</Alert>
</div>
);
}
テーマ機能の活用
より高度な使い方として、テーマ機能を使った統一されたデザインシステムの構築も可能です:
typescript// theme/theme.ts
export const theme = {
colors: {
primary: '#007bff',
secondary: '#6c757d',
success: '#28a745',
danger: '#dc3545',
warning: '#ffc107',
info: '#17a2b8',
},
spacing: {
xs: '4px',
sm: '8px',
md: '16px',
lg: '24px',
xl: '32px',
},
fontSize: {
sm: '14px',
md: '16px',
lg: '18px',
xl: '24px',
},
};
// TypeScript用の型定義
export type Theme = typeof theme;
typescript// components/ThemedButton.tsx
import styled from '@emotion/styled';
import { Theme } from '../theme/theme';
interface ThemedButtonProps {
variant?: 'primary' | 'secondary';
size?: 'sm' | 'md' | 'lg';
}
const ThemedButton = styled.button<ThemedButtonProps>`
background: ${({
theme,
variant = 'primary',
}: {
theme: Theme;
variant?: 'primary' | 'secondary';
}) => theme.colors[variant]};
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: opacity 0.2s ease;
padding: ${({
theme,
size = 'md',
}: {
theme: Theme;
size?: 'sm' | 'md' | 'lg';
}) => {
switch (size) {
case 'sm':
return `${theme.spacing.sm} ${theme.spacing.md}`;
case 'lg':
return `${theme.spacing.lg} ${theme.spacing.xl}`;
default:
return `${theme.spacing.md} ${theme.spacing.lg}`;
}
}};
font-size: ${({
theme,
size = 'md',
}: {
theme: Theme;
size?: 'sm' | 'md' | 'lg';
}) => theme.fontSize[size]};
&:hover {
opacity: 0.8;
}
`;
export { ThemedButton };
実際の使用例とエラーハンドリング
実際の開発では、以下のようなエラーが発生することがあります:
typescript// よくあるエラー例
const BrokenComponent = styled.div`
background: ${(props) =>
props.color}; // undefinedになる可能性
padding: ${(props) => props.size}px; // 型エラーの可能性
`;
// 改善版
interface ComponentProps {
color?: string;
size?: number;
}
const SafeComponent = styled.div<ComponentProps>`
background: ${({ color = '#fff' }) => color};
padding: ${({ size = 16 }) => size}px;
`;
まとめ
Emotion の導入メリット
本記事では、Emotion の基本的な使い方から実践的な活用方法まで、3 分で始められる範囲をご紹介しました。
主要なメリットの再確認
-
学習コストの低さ 従来の CSS の知識をそのまま活用できるため、新しい概念を覚える必要が最小限です。
-
型安全性 TypeScript との組み合わせにより、スタイルプロパティの補完やエラーチェックが利用できます。
-
優れた開発体験 Hot Reload によるリアルタイムな変更確認や、VSCode での豊富な拡張機能が利用できます。
-
パフォーマンス 必要なスタイルのみがバンドルされ、実行時のパフォーマンスも優秀です。
次のステップへの案内
Emotion の基本を理解したら、以下のステップに進むことをお勧めします:
ステップ | 内容 | 所要時間 |
---|---|---|
1 | アニメーション機能の習得 | 30 分 |
2 | テーマシステムの構築 | 1 時間 |
3 | パフォーマンス最適化 | 1 時間 |
4 | テストの実装 | 1 時間 |
実際のプロジェクトでの活用
実際の開発では、以下のような場面で Emotion の力を発揮できます:
-
デザインシステムの構築 一貫した UI/UX を提供するためのコンポーネントライブラリ作成
-
レスポンシブデザイン メディアクエリを使った柔軟なレイアウト調整
-
動的テーマ切り替え ダークモード対応やユーザーカスタマイズ機能
今回学んだ基本的な使い方を基に、ぜひ実際のプロジェクトで Emotion を活用してみてください。きっと、スタイリングの新しい可能性を発見できるでしょう。
関連リンク
- blog
Culture, Automation, Measurement, Sharing. アジャイル文化を拡張する DevOps の考え方
- blog
開発と運用、まだ壁があるの?アジャイルと DevOps をかけ合わせて開発を爆速にする方法
- blog
スクラムマスターは雑用係じゃない!チームのポテンシャルを 120%引き出すための仕事術
- blog
「アジャイルやってるつもり」になってない?現場でよく見る悲劇と、僕らがどう乗り越えてきたかの話
- blog
強いチームは 1 日にしてならず。心理的安全性を育むチームビルディングの鉄則
- blog
トヨタ生産方式から生まれた「リーン」。アジャイル開発者が知っておくべきその本質
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来
- review
人類はなぜ地球を支配できた?『サピエンス全史 上巻』ユヴァル・ノア・ハラリが解き明かす驚愕の真実