CSS-in-JS しーえすえすいんじぇいえす
簡単に言うとこんな感じ!
CSSのスタイル(見た目のデザイン)を、JavaScriptのコードの中に直接書いちゃう手法だよ!「このボタンのデザイン」と「このボタンの動き」を同じファイルにまとめて書けるから、パーツごとにデザインを管理しやすくなるんだ!
CSS-in-JSとは
CSS-in-JSとは、Webページのスタイル(見た目・デザイン)を定義するCSSを、JavaScriptのコードの中に記述するアプローチの総称です。従来はHTMLファイル・CSSファイル・JavaScriptファイルをそれぞれ別に管理するのが一般的でしたが、CSS-in-JSではスタイルをJavaScriptのロジックと同じファイルにまとめて書きます。
ReactやVueのようなコンポーネント(部品)ベースの開発が主流になるにつれて、「このコンポーネントに対応するスタイルはここ」と一対一で管理したいニーズが高まりました。CSS-in-JSはそのニーズに応えるために生まれた手法で、styled-componentsやEmotionといったライブラリが広く使われています。
スタイルがJavaScriptの変数や関数と同じ場所に書かれるため、動的なスタイル変更(ボタンが押されたら色が変わる、など)もシンプルに実装できます。一方で、実行時にスタイルを生成するためパフォーマンスへの影響も議論されており、メリット・デメリットを理解した上で採用を判断することが重要です。
CSS-in-JSの仕組みと特徴
CSS-in-JSの主なメリット・デメリットを整理します。
| 特徴 | 内容 |
|---|---|
| スコープの閉じ込め | 自動生成されたクラス名でスタイルが他のコンポーネントに漏れない |
| 動的スタイル | Propsや状態に応じてスタイルをJavaScriptで変化させられる |
| コロケーション | デザインとロジックを同じファイルで管理できる |
| デッドコード排除 | 使われていないスタイルは自動的に含まれない |
| 実行時コスト | ブラウザでJSを実行してCSSを生成するためパフォーマンスに影響が出る場合がある |
| 学習コスト | 独自の記法やライブラリへの習熟が必要 |
styled-componentsの記法例
import styled from 'styled-components';
// ボタンコンポーネントにスタイルを直接定義
const Button = styled.button`
background: ${props => props.primary ? '#1e3a8a' : '#dbeafe'};
color: ${props => props.primary ? '#fff' : '#1e3a8a'};
padding: 0.5rem 1.2rem;
border-radius: 6px;
border: none;
cursor: pointer;
`;
// 使う側はただのコンポーネントとして扱える
<Button primary>送信</Button>
<Button>キャンセル</Button>
主要ライブラリの比較
| ライブラリ | 動作タイミング | 特徴 |
|---|---|---|
| styled-components | 実行時(Runtime) | テンプレートリテラルで書けて直感的 |
| Emotion | 実行時(Runtime) | 柔軟性が高く、styled-componentsと互換性あり |
| vanilla-extract | ビルド時(Zero-runtime) | TypeScript型安全、パフォーマンス重視 |
| Linaria | ビルド時(Zero-runtime) | styled-componentsライクな書き方でゼロランタイム |
歴史と背景
- 2014年: FacebookエンジニアのChristopher Chedeau(vjeux)がCSS設計の課題(グローバル汚染・スコープの難しさなど)を発表し、CSS-in-JSというコンセプトが注目を集め始める
- 2016年: styled-components がリリース。テンプレートリテラルでCSSを書けるAPIが革新的として広まる
- 2017年: Emotion が登場し、パフォーマンス改善版として普及
- 2019〜2020年: コンポーネント設計の普及とともにCSS-in-JSが本格的にデファクトのひとつへ
- 2021年〜: サーバーサイドレンダリング(SSR)やEdge環境でのパフォーマンス問題が議論され始め、Zero-runtime CSS-in-JS(ビルド時にCSSを生成する手法)への移行が進む
- 2023年〜: Next.js App RouterなどのRSC(React Server Components)環境では実行時CSS-in-JSが動かないケースが増え、vanilla-extractやTailwind CSSなどへの移行も加速
従来のCSS管理手法との比較
CSS-in-JS以外にもCSSを管理する方法はいくつかあります。どれが最適かはプロジェクトの規模・チームの習熟度・使用フレームワークによって変わります。
Runtime vs Zero-runtime の違い
CSS-in-JSの中でも近年は「いつCSSを生成するか」が重要な選択肢になっています。
【Runtime CSS-in-JS】
ブラウザ上でJSが実行される
→ その場でCSSを生成してDOMに挿入
→ 動的な変更に強いがパフォーマンスコストあり
例: styled-components, Emotion
【Zero-runtime CSS-in-JS】
ビルド時(開発者のPC上)にCSSを生成
→ 通常の .css ファイルとして出力
→ ブラウザでのJSコストほぼゼロ
例: vanilla-extract, Linaria
関連用語
- コンポーネント — UIを部品単位で管理するReact/Vueの設計概念
- CSS Modules — ファイル単位でCSSのスコープを閉じ込める標準的な手法
- Tailwind CSS — ユーティリティクラスを組み合わせてスタイリングするフレームワーク
- React — Facebookが開発したコンポーネントベースのUIライブラリ
- サーバーサイドレンダリング(SSR) — サーバー側でHTMLを生成して返す手法。CSS-in-JSとの相性が課題になりやすい
- Next.js — Reactベースのフルスタックフレームワーク。RSC環境でCSS-in-JSの選択に影響あり
- Sass / SCSS — CSSを拡張した従来型のスタイルシート言語
- ビルドツール — WebpackやViteなど、JSやCSSをまとめて最適化するツール