はじめに
Reactでスタイルを適用する方法は多岐にわたります。それぞれに特徴があり、プロジェクトの規模や要件によって最適な手法は異なります。
この記事では、Reactで主に使われる6つのスタイリング手法について、特徴や使い分けのポイントを解説します。
1. 通常のCSSファイルインポート
基本的な使い方
最もシンプルな方法です。CSSファイルを作成し、コンポーネントでインポートします。
/* Button.css */
.button {
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
}
.button:hover {
background-color: #0056b3;
}
import './Button.css';
function Button() {
return <button className="button">クリック</button>;
}
特徴
- CSSファイルとJavaScriptファイルを分離
- クラス名はグローバルスコープになる
- 従来のWeb開発と同じ書き方
メリット・デメリット
メリット:
- 学習コストが低い(既存のCSS知識がそのまま使える)
- ツールやライブラリのインストールが不要
- CSSファイルとして分離されているため、スタイルの管理がしやすい
- エディタのCSS補完機能がそのまま使える
デメリット:
- クラス名がグローバルスコープのため、名前の衝突が発生しやすい
- 大規模プロジェクトではBEMなどの命名規則が必要
- 使われていないスタイルの特定が難しい
- コンポーネントとスタイルの結びつきが弱い
適している場面
- 小規模なプロジェクト
- CSSフレームワーク(Bootstrap、Tailwind CSSなど)を使用する場合
- グローバルなスタイル(リセットCSS、共通変数など)を定義する場合
- チームメンバーがCSSに慣れている場合
2. CSS Modules(CSSモジュール)
基本的な使い方
ファイル名を*.module.cssにすることで、CSSモジュールとして扱われます。
/* Button.module.css */
.button {
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
}
.button:hover {
background-color: #0056b3;
}
import styles from './Button.module.css';
function Button() {
return <button className={styles.button}>クリック</button>;
}
ビルド時にbutton_abc123のようなユニークなクラス名に変換されます。
特徴
- クラス名が自動的にローカルスコープになる
- CSSファイルの内容がJavaScriptオブジェクトとしてインポートされる
- Create React AppやNext.jsなどで標準サポート
メリット・デメリット
メリット:
- クラス名の衝突を自動的に防げる
- コンポーネント単位でスタイルをスコープできる
- IDEの補完機能が使える(タイポを防げる)
- 通常のCSSの書き方がそのまま使える
- 追加のライブラリが不要
デメリット:
- 複数のクラスを適用する際に少し冗長になる
- グローバルなスタイルを定義する場合は
:global()を使う必要がある - 動的なクラス名の生成がやや面倒
適している場面
- 中〜大規模なプロジェクト
- コンポーネントの再利用性を重視する場合
- クラス名の衝突を避けたい場合
- CSSの知識を活かしつつ、モダンな開発をしたい場合
3. Inline Styles(インラインスタイル)
基本的な使い方
JavaScriptオブジェクトとしてスタイルを定義し、styleプロパティに渡します。
function Button() {
const buttonStyle = {
backgroundColor: '#007bff',
color: 'white',
padding: '10px 20px',
border: 'none',
borderRadius: '4px',
};
return <button style={buttonStyle}>クリック</button>;
}
特徴
- スタイルをJavaScriptオブジェクトとして定義
- プロパティ名はキャメルケース(
background-color→backgroundColor) - 値は文字列で指定(数値の場合は
pxが自動付与される)
メリット・デメリット
メリット:
- JavaScript内で完結するため、動的なスタイルの変更が簡単
- コンポーネントの状態やpropsに基づいたスタイリングが直感的
- クラス名の管理が不要
- スコープの心配がない
デメリット:
- 疑似クラス(
:hover、:focusなど)や疑似要素(::before、::after)が使えない - メディアクエリが使えない
- パフォーマンスが若干悪い(再レンダリングごとにスタイルオブジェクトが生成される)
- CSSの高度な機能が使えない
適している場面
- 動的に変わるスタイル(アニメーション、テーマ切り替えなど)
- コンポーネントの状態に応じたスタイリング
- 小さなコンポーネントやプロトタイプ
- propsベースでスタイルを変更したい場合
// 動的なスタイルの例
function ProgressBar({ progress }) {
return (
<div style={{
width: '100%',
height: '20px',
backgroundColor: '#e0e0e0'
}}>
<div style={{
width: `${progress}%`,
height: '100%',
backgroundColor: '#007bff',
transition: 'width 0.3s ease'
}} />
</div>
);
}
4. Styled JSX
基本的な使い方
コンポーネント内に<style jsx>タグを記述します。Next.jsに標準搭載されています。
function Button() {
return (
<>
<button className="button">クリック</button>
<style jsx>{`
.button {
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
}
.button:hover {
background-color: #0056b3;
}
`}</style>
</>
);
}
特徴
- コンポーネント内にCSSを記述
- スタイルが自動的にそのコンポーネント内にスコープされる
- Next.jsでは追加設定なしで使える
- 通常のCSSの構文をそのまま使える
メリット・デメリット
メリット:
- コンポーネントとスタイルが同じファイルに記述できる
- 自動的にスコープされるため、クラス名の衝突がない
- 通常のCSS構文が使える(疑似クラス、メディアクエリなど)
- Next.jsでは標準搭載
デメリット:
- Next.js以外では追加のセットアップが必要
- スタイルが文字列として扱われるため、IDEの補完が効きにくい
- グローバルスタイルを定義する場合は
<style jsx global>を使う必要がある - コンポーネントが大きくなると可読性が下がる
適している場面
- Next.jsを使用しているプロジェクト
- コンポーネントとスタイルを一箇所で管理したい場合
- 小〜中規模のコンポーネント
- サーバーサイドレンダリング(SSR)を使う場合
5. styled-components
※styled-compoments は更新の停止を正式にアナウンス済みです。
6のemotionを使うことを推奨いたします。
基本的な使い方
タグ付きテンプレートリテラルを使って、スタイル付きコンポーネントを作成します。
import styled from 'styled-components';
const Button = styled.button`
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
&:hover {
background-color: #0056b3;
}
`;
function App() {
return <Button>クリック</Button>;
}
特徴
- CSS-in-JSの代表的なライブラリ
- コンポーネント自体がスタイルを持つ
- propsを使った動的なスタイリングが可能
- 自動的にユニークなクラス名が生成される
// propsを使った動的スタイリング
const Button = styled.button`
background-color: ${props => props.primary ? '#007bff' : '#6c757d'};
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
&:hover {
opacity: 0.8;
}
`;
function App() {
return (
<>
<Button primary>プライマリ</Button>
<Button>セカンダリ</Button>
</>
);
}
メリット・デメリット
メリット:
- コンポーネントとスタイルが密結合で管理しやすい
- propsベースの動的スタイリングが直感的
- TypeScriptとの相性が良い
- テーマ機能(ThemeProvider)が充実
- 使われていないスタイルが自動的に削除される
- エコシステムが充実している
デメリット:
- 学習コストがやや高い
- バンドルサイズが増加する
- パフォーマンスが通常のCSSより若干劣る
- スタイルの再利用にはやや工夫が必要
適している場面
- 中〜大規模なSPA(Single Page Application)
- コンポーネントライブラリを作成する場合
- テーマ機能が必要な場合
- TypeScriptを使用しているプロジェクト
- 動的なスタイリングを多用する場合
6. Emotion
基本的な使い方
Emotionには2つの主要な記法があります。
css prop記法:
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
function Button() {
return (
<button
css={css`
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
&:hover {
background-color: #0056b3;
}
`}
>
クリック
</button>
);
}
styled記法:
import styled from '@emotion/styled';
const Button = styled.button`
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
&:hover {
background-color: #0056b3;
}
`;
function App() {
return <Button>クリック</Button>;
}
特徴
- CSS-in-JSライブラリの一つ
- styled-componentsと似た機能を持つ
- パフォーマンスに優れている
- 柔軟性が高く、複数の記法をサポート
メリット・デメリット
メリット:
- パフォーマンスが優れている(styled-componentsより高速)
- バンドルサイズが小さい
- 複数の記法から選べる柔軟性
- TypeScriptのサポートが充実
- SSR(サーバーサイドレンダリング)に対応
- 既存のstyled-componentsからの移行が容易
デメリット:
- 学習コストがやや高い
- css prop記法を使う場合、追加の設定が必要
- styled-componentsより認知度が低い
適している場面
- パフォーマンスを重視するプロジェクト
- バンドルサイズを抑えたい場合
- 複数のスタイリング記法を組み合わせたい場合
- TypeScriptを使用しているプロジェクト
- styled-componentsからの乗り換えを検討している場合
6つの手法を比較表で整理
| 手法 | スコープ | 学習コスト | パフォーマンス | 動的スタイル | 追加ライブラリ |
|---|---|---|---|---|---|
| 通常のCSS | グローバル | 低 | 高 | 難しい | 不要 |
| CSS Modules | ローカル | 低 | 高 | やや難しい | 不要 |
| Inline Styles | ローカル | 低 | 中 | 簡単 | 不要 |
| Styled JSX | ローカル | 中 | 高 | 可能 | Next.jsは不要 |
| styled-components | ローカル | 中 | 中 | 簡単 | 必要 |
| Emotion | ローカル | 中 | 高 | 簡単 | 必要 |
補足:
- スコープ:スタイルが適用される範囲
- 学習コスト:習得にかかる時間と労力
- パフォーマンス:実行時のパフォーマンス
- 動的スタイル:状態やpropsに応じたスタイル変更のしやすさ
- 追加ライブラリ:npm installが必要かどうか
どの手法を選ぶべきか
プロジェクトの特性に応じて最適な手法を選びましょう。
※あくまで一例です
選択のポイント:
-
小規模プロジェクト・プロトタイプ
- 通常のCSSまたはInline Styles
-
中規模プロジェクト
- CSS Modulesがバランスが良い
-
大規模プロジェクト
- styled-componentsまたはEmotion
-
Next.jsプロジェクト
- Styled JSXが手軽
-
パフォーマンス重視
- CSS ModulesまたはEmotion
-
動的スタイルが多い
- styled-components、Emotion、またはInline Styles
まとめ
Reactでのスタイリング手法は多様で、それぞれに長所と短所があります。
基本的な指針:
- グローバルなスタイルやリセットCSSは通常のCSSで
- コンポーネント固有のスタイルはCSS ModulesやCSS-in-JSで
- 動的なスタイルが必要な部分はInline StylesやCSS-in-JSで
多くのプロジェクトでは、これらの手法を組み合わせて使うのが実践的です。プロジェクトの要件やチームの習熟度に合わせて、最適な手法を選択してください。
まずは小さなプロジェクトで試してみて、自分やチームに合った手法を見つけることをおすすめします。