Reactのスタイリング手法
Reactでのスタイリングの選択肢
まずは「種類が多すぎてよく分からない状態」を整理しておきます。
Reactでよく使われるスタイル手法はざっくりこのあたりです:
- 素のCSS(グローバルCSS)
index.cssみたいな普通のCSSファイルに書いて、classNameで当てる
- CSS Modules
Button.module.cssのようなファイル単位でクラス名をコンポーネントにひも付けるやり方
- CSS-in-JS
styled-components,Emotionなど- JSファイルの中に
const Button = styled.buttonみたいに書く
- ユーティリティクラス系(Tailwind CSSなど)
className="px-4 py-2 bg-blue-500 text-white rounded"みたいに小さなクラスを組み合わせて作る
- インラインスタイル
style={{ color: 'red', fontSize: 20 }}のようにJSオブジェクトで指定
実務的なおすすめ:
- 最初のうちは、 「素のCSS or CSS Modules」+インラインスタイル
- 慣れてきたら、「 Tailwind」か「CSS-in-JS」
一番素直なやり方:グローバルCSS + className
Viteの初期テンプレートだと src/index.css が読み込まれていて、
そこに書いたCSSがアプリ全体に効くようになっています。
① CSSを書く
/* src/index.css */
.app-root {
max-width: 800px;
margin: 0 auto;
padding: 16px;
font-family: system-ui, sans-serif;
}
.button-primary {
padding: 8px 16px;
border-radius: 4px;
border: none;
background-color: #2563eb;
color: white;
cursor: pointer;
}
.button-primary:hover {
background-color: #1d4ed8;
}② Reactで className を付ける
// src/App.jsx
export default function App() {
return (
<div className="app-root">
<h1>Reactアプリ</h1>
<button className="button-primary">送信</button>
</div>
)
}ポイント:
- 普通のHTMLと同じ感覚で
classの代わりにclassName - 全コンポーネントから
.button-primaryを使い回せる
デメリット:
- クラス名がグローバル空間にばら撒かれるので、
- 名前衝突しやすい
- どのファイルがどのスタイルを参照しているか追いにくくなる
これを少しマシにするために、
BEM記法(block__element--modifier)を使うこともよくあります:
.todo-item { ... }
.todo-item__title { ... }
.todo-item__delete-button { ... }最初のうちは「小さめのアプリ + グローバルCSS」で十分ですが、
コンポーネント数が増えてくると「コンポーネントごとにスタイルを閉じたい」欲求が出てきます。
そこで出てくるのが CSS Modules です。
CSS Modules:コンポーネントごとにCSSを閉じ込める
CSS Modulesは、「このコンポーネント専用のCSSファイル」を作って、クラス名の衝突を自動的に防いでくれる仕組みです。
① ファイル名を *.module.css にする
/* src/Button.module.css */
.button {
padding: 8px 16px;
border-radius: 9999px;
border: none;
background-color: #16a34a;
color: white;
cursor: pointer;
}
.buttonDisabled {
opacity: 0.5;
cursor: not-allowed;
}② React側でimportして使う
// src/Button.jsx
import styles from './Button.module.css'
export default function Button({ children, disabled, ...props }) {
const className = disabled
? `${styles.button} ${styles.buttonDisabled}`
: styles.button
return (
<button className={className} disabled={disabled} {...props}>
{children}
</button>
)
}ここで起きていること:
styles.button⇒ 実際にはbutton_aj3kd9みたいなユニークなクラス名に変換されるButton.module.cssのクラスはButton.jsxに閉じたスコープとして扱える- 他のコンポーネントで
styles.buttonと書いても、別ファイルなら別物
メリット:
- クラス名の衝突をほぼ気にしなくていい
- 「コンポーネント単位のスタイル」という構造になって、頭の整理がしやすい
- 導入も簡単(Viteならデフォルト対応)
個人開発〜中規模くらいまでなら CSS Modules だけで十分です。
CSS-in-JS:styled-components / Emotion のイメージ
CSS-in-JSは、「JSの中にスタイルを書くことで、完全にコンポーネントとスタイルを1ファイルに閉じる」方向の手法です。
代表的なのが styled-components と @emotion/styled。
styled-components の例
(※実際に使うには npm install styled-components が必要)
// Button.jsx
import styled from 'styled-components'
const Button = styled.button`
padding: 8px 16px;
border-radius: 9999px;
border: none;
background-color: #2563eb;
color: white;
cursor: pointer;
&:hover {
background-color: #1d4ed8;
}
&[disabled] {
opacity: 0.5;
cursor: not-allowed;
}
`
export default Button使う側:
import Button from './Button'
export default function App() {
return <Button>クリック</Button>
}メリット:
- コンポーネントとスタイルが同じファイルにあるので、1ファイル見れば完結
- propsに応じてスタイルを分岐しやすい
const Button = styled.button`
background-color: ${({ primary }) => (primary ? '#2563eb' : '#6b7280')};
`デメリット:
- ライブラリ導入が必要
- ランタイムでスタイル生成するため、パフォーマンス・バンドルサイズを気にするケースもある
- セットアップや設計思想の学習コストがやや重め
最初からこれに突っ込む必要は薄いので、
「CSS Modulesで慣れてきて、もう少し高度なことがしたくなってから」検討でOKです。
Tailwind CSS:ユーティリティクラスで組み立てる
Tailwind CSS は、「小さなユーティリティクラスを組み合わせてデザインするスタイルフレームワーク」です。
例:
<button className="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded">
送信
</button>px-4⇒ 左右パディングpy-2⇒ 上下パディングbg-blue-500⇒ 背景色hover:bg-blue-600⇒ hover時の背景色rounded⇒ 角丸
メリット:
- コンポーネントファイル内だけで見た目が完結
- クラス名を1つ1つ考える必要がない(
btn-primaryとか命名しない) - 設計次第でコンポーネント設計と相性が良い(小さなパーツの組み合わせ)
デメリット:
- HTML(JSX)の
classNameが長くなりがち - Tailwind特有のクラス名に慣れる必要あり
- セットアップがやや重め(PostCSS, configなど)
個人開発で「スピード重視」「デザインそこそこ」のときはかなり強いですが、
Reactそのものに慣れる前にいきなりTailwindから入ると、情報量が多くなりコードの理解が難しくなります。
インラインスタイル
インラインスタイルは、
<div style={{ color: 'red', fontSize: 24 }}>テキスト</div>のように、JSオブジェクトでスタイルを指定する方法です。
特徴:
- 値は常に文字列ではなくJSの値:
fontSize: 24('24px'ではない)backgroundColor(background-colorではなくキャメルケース)
- ホバーやメディアクエリ、擬似要素など 普通のCSSで書けることがほとんど使えない
なので、インラインスタイルは 「一時的なスタイル」「計算結果で決まる1〜2プロパティ」くらいに留めるのが現実的です。
例:
const ProgressBar = ({ progress }) => {
return (
<div style={{ width: 200, height: 10, backgroundColor: '#e5e7eb' }}>
<div
style={{
width: `${progress}%`,
height: '100%',
backgroundColor: '#22c55e',
transition: 'width 0.2s ease',
}}
/>
</div>
)
}こういう「動的に変化する幅・色」をサクッと書くときだけ使うのが良いです。
どれを選べばいいか?
React初学〜中級に向かう段階では、こんなステップがおすすめです:
- まずは素のCSS + className
- Viteの
index.cssでOK - 小さなコンポーネントでスタイルを当てる感覚を掴む
- Viteの
- 次に CSS Modules を導入
- コンポーネント単位で
*.module.cssを作る import styles from './Xxx.module.css'を使いこなす- 「デザイン変更時は、そのコンポーネントのCSSだけ見ればいい」状態を目指す
- コンポーネント単位で
- そこから先は好みと案件次第で分岐:
- デザイン用コンポーネントを量産したい ⇒ CSS-in-JS(styled-components / Emotion)
- とにかくUIを爆速で組みたい ⇒ Tailwind CSS
いきなり全部を覚えなくてよくて、「CSS Modulesに慣れる」だけで、React×スタイリングとしてはかなり実戦レベルと言って良いです。
まとめ
- Reactのスタイリングは
- グローバルCSS
- CSS Modules
- CSS-in-JS(styled-components/Emotion)
- Tailwind CSS
- インラインスタイル
など様々だが、まずはCSS Modulesに慣れるのが現実的なライン
- CSS Modulesは
*.module.cssを作ってimport styles from '...'className={styles.xxx}でクラス名衝突を気にせず書ける
- CSS-in-JSやTailwindは強力だが、Reactの基礎に慣れてから着手でも遅くない
- インラインスタイルは「計算結果で決まる少数のプロパティ」くらいに絞ると扱いやすい
コメント