
従来のテーマ開発では、functions.phpでエディター機能を有効化し、style.cssや追加CSSで色、余白、文字サイズを定義していた。ブロックごとの例外が増えると、セレクターの詳細度が上がる。最終的には、どのCSSが適用されているのかを確認するために、ブラウザーの開発者ツールを開く時間が増える。
theme.jsonは、この問題を設定ファイル中心の設計に変える。ブロックエディターの設定、サイト全体のスタイル、要素ごとのスタイル、ブロック固有のスタイルを一つの構造で管理できる。WordPressのテーマ開発において、theme.jsonによるスタイル管理は装飾方法の変更ではない。テーマの依存関係を整理するための設計手法である。
theme.jsonが変えるWordPressテーマ開発のパラダイム
theme.jsonはWordPress 5.8で導入された。ブロックエディターの設定とスタイルをJSON形式で定義するためのファイルである。
導入以前は、テーマの機能をfunctions.phpに記述する構成が一般的だった。たとえば、エディターで使用できる色やフォントサイズを制限する場合、テーマサポートを追加し、CSS側でも同じ値を管理する必要があった。
この構成には、値の重複がある。
- エディターで表示する色をPHPで定義する
- フロントエンド用の色をCSSで定義する
- ブロックごとの例外を個別のセレクターで上書きする
- テーマ更新やプラグイン追加のたびに優先順位を再確認する
設定の情報と表示の情報が別々に存在するため、変更箇所が増える。色を一つ変更するだけでも、PHP、CSS、ブロック設定の複数箇所を修正する構成になりやすい。
theme.jsonでは、これらの値をテーマ設定としてまとめる。WordPressは設定内容を読み取り、エディターのUIとフロントエンド用のCSSカスタムプロパティに反映する。
theme.jsonの価値は、CSSを消すことではない。スタイルの定義元を一つにし、変更経路を短くすることである。トップレベルプロパティの役割
theme.jsonの基本構造には、主に次のプロパティがある。
| プロパティ | 主な役割 | 設計上の位置づけ |
|---|---|---|
$schema | JSONの構造をエディターや開発ツールに伝える | 記述支援と検証 |
version | 使用する仕様バージョンを指定する | WordPressとの互換性管理 |
settings | エディターで許可する機能やプリセットを定義する | 編集可能範囲の制御 |
styles | サイト全体、要素、ブロックの見た目を定義する | スタイルの適用 |
customTemplates | カスタムテンプレートの情報を定義する | ブロックテーマの構造 |
templateParts | ヘッダーやフッターなどのテンプレート部品を定義する | レイアウト部品の管理 |
patterns | ブロックパターンの登録情報を定義する | 再利用可能なUIの管理 |
すべてを最初から設定する必要はない。スタイル管理を目的にする場合、中心になるのはversion、settings、stylesである。
customTemplates、templateParts、patternsはブロックテーマの構造管理に関係する。サイト全体の設計を進める過程で必要になるが、色や余白の定義と同じ階層の問題として扱うと、ファイルの責務が曖昧になる。
settingsとstylesは別の責務である
settingsは、何を使えるようにするかを定義する。
たとえば、カラーパレット、文字サイズ、余白調整、レイアウト設定などが該当する。編集画面に表示する選択肢を制御する役割である。
一方のstylesは、実際にどのような見た目にするかを定義する。本文の文字色、ページ全体の背景色、ボタンの角丸、段落の行間などが該当する。
この二つを混同すると、編集UIに不要な選択肢が表示される。逆に、設定を制限しすぎると、編集者が必要な調整を行えない。
テーマ開発では、次の順序で設計すると依存関係が整理しやすい。
1. デザイン上許可する値をsettingsで定義する
2. サイト全体の初期値をstylesのRootで定義する
3. HTML要素に対する共通ルールをstylesのElementsで定義する
4. 特定ブロックだけ異なる場合にBlocksで上書きする
5. 例外だけを追加CSSで処理する
最初からブロック単位のCSSを書くと、共通化できるルールまで個別管理になる。ブロックテーマでは、共通値を先に設計し、例外の発生箇所を限定する方が保守しやすい。
Root・Elements・Blocksという3つの適用階層
stylesには、主に三つの適用階層がある。Root、Elements、Blocksである。
同じスタイル指定でも、どの階層に置くかで影響範囲が変わる。ここを理解しないまま設定を増やすと、意図しない上書きが発生する。
Rootはサイト全体の基準値を置く
Rootは、サイト全体に適用するスタイルを定義する場所である。
本文の文字色、ページ背景、基本的な文字サイズ、行間、コンテンツ幅などが対象になる。Rootで設定した値は、個別ブロックに明示的な指定がない限り、サイト全体の基準として利用される。
たとえば、サイトの本文色を暗いグレーに統一する場合、段落、リスト、見出しごとに同じ色を指定する必要はない。Rootに基準値を置き、必要な要素だけをElementsやBlocksで変更する。
この設計には二つの利点がある。
一つ目は変更範囲が明確になることだ。本文色を変更する場合、Rootの値を変更すればよい。複数のブロック用CSSを検索する必要はない。
二つ目は、値の継承関係を利用できることだ。個別指定を減らすことで、CSSの詳細度競合を抑えられる。
ただし、Rootにすべての見た目を詰め込むのは適切ではない。ボタンの背景色やコードブロックの余白は、RootではなくElementsまたはBlocksの責務である。Rootはサイトの基準値に限定する必要がある。
ElementsはHTML要素の共通ルールを置く
Elementsでは、リンクやボタンなどの要素に対するスタイルを管理する。
サイト内のリンク色を統一する場合、各ブロックのリンクに個別のCSSを書く必要はない。Elementsのリンク設定に共通値を置くことで、段落内のリンク、リスト内のリンク、カラム内のリンクに同じルールを適用できる。
ボタンも同様である。ボタンの背景色、文字色、角丸、余白をElementsで共通化すれば、ボタンブロックの個別設定を減らせる。
ただし、WordPressのブロックは単純なHTML要素ではない。ブロック側の設定やクラス、プラグインが出力するマークアップによって、最終的なCSSの適用結果が変わることがある。
したがって、Elementsは「すべての見た目を強制する場所」ではない。複数のブロックに共通する要素の初期値を置く場所である。
Blocksはブロック固有の差分を定義する
Blocksでは、特定ブロックにだけ適用するスタイルを定義する。
対象は、段落、見出し、ボタン、コード、画像、グループなどのコアブロックである。core/paragraphやcore/codeのようにブロック名を指定し、そのブロックに対して文字サイズ、余白、色、境界線などを設定する。
ここで注意すべきなのは、Blocksに共通ルールを重複して書かないことである。
例えば、本文色をRootで定義し、さらに段落、リスト、引用、グループに同じ文字色を指定すると、設定が分散する。将来、本文色を変更するときに複数箇所を修正することになる。
ブロック固有の指定が必要なケースは限定される。
- コードブロックだけ背景色を変える
- 引用ブロックだけ左側に境界線を表示する
- 見出しブロックだけ文字間隔を調整する
- 画像ブロックだけ角丸を適用する
- ボタンブロックだけ内側の余白を変更する
このような差分をBlocksに置く。共通値はRootまたはElementsに残す。
3階層を上書き関係として設計する
Root、Elements、Blocksは、単に設定を置く場所が三つあるという話ではない。スタイルの適用範囲を段階的に狭める構造である。
設計上は、次のように考えるとよい。
- Root:サイト全体の初期値
- Elements:HTML要素単位の共通値
- Blocks:ブロック単位の差分
- 追加CSS:theme.jsonで表現できない例外
この順序を逆にすると、Blocksにすべての指定が集まる。ファイルは動作するが、テーマ全体の計算量は増える。ここでいう計算量は、プログラムの実行時間だけを指さない。変更時に確認すべき定義数と依存関係の数も、実務上のコストである。
appearanceToolsによるグラフィカルUIの統合管理
settings.appearanceToolsを有効にすると、枠線、背景、スペーシングなどのグラフィカルUIコントロールをまとめてエディター上で利用できる。
個別の設定を一つずつ有効にする方法もある。しかし、サイト編集者に幅広い調整を許可するテーマでは、appearanceToolsによる一括設定が有効である。
一方、すべてのプロジェクトに適しているわけではない。編集者が自由に余白や背景を変更できると、デザインシステムの制約が崩れる可能性がある。
自由度と一貫性は反比例する
サイト制作では、編集者の自由度を上げれば運用しやすくなるとは限らない。
たとえば、複数人が記事を作成するメディアサイトでは、ブロックごとの余白を自由に設定できると、ページ間のリズムが崩れやすい。エディター上では正しく見えても、記事ごとに段落間隔や見出しの余白が変わり、サイト全体の一貫性が失われる。
appearanceToolsを有効にするかどうかは、次の条件で判断する。
- 編集者がレイアウトを変更する運用か
- デザインシステムの制約を優先するか
- 固定ページと記事で編集権限が異なるか
- ブロックパターンを中心に運用するか
- CSSで許可値を限定する必要があるか
自由度を求めるサイトでは有効である。ブランド表現を厳密に固定するサイトでは、個別設定を制御した方がよい。
プリセットは値の選択肢を制御する
カラーパレットや文字サイズは、任意の値を入力させるより、プリセットとして定義した方が管理しやすい。
プリセットに登録した値は、エディター上の選択肢として扱える。テーマ側で定義した色を編集者が選択するため、ページごとに異なる色コードを入力する状態を避けられる。
この構成では、デザインの値がCSSカスタムプロパティとして出力される。テーマ側が直接色コードを繰り返し記述する必要がない。
色を変更する場合も、プリセットの値を変更すればよい。ブロック側でプリセットを参照していれば、複数のページやブロックに反映される。
ただし、既存コンテンツに直接指定された値がある場合は別である。過去の記事にインラインスタイルや個別クラスが保存されていると、テーマ側の変更だけでは表示が完全に統一されないことがある。
新規テーマでは、最初からプリセット中心で設計する方が安全である。既存テーマに導入する場合は、保存済みコンテンツとの依存関係を確認する必要がある。
CSSカスタムプロパティの自動生成と詳細度競合の回避
theme.jsonを利用すると、WordPressは設定内容に応じてCSSカスタムプロパティを出力する。代表的な形式として、--wp--preset--*のような変数が生成される。
この仕組みにより、テーマ開発者は同じ値を複数のCSSセレクターに書く必要がなくなる。
CSSカスタムプロパティの利点は、値の共通化だけではない。スタイルの参照先が明確になる点にある。
例えば、ブランドカラーを複数のボタン、リンク、見出しで利用する場合、各セレクターに色コードを直接記述すると、変更漏れが発生する。カスタムプロパティを利用すれば、定義した値を複数の場所から参照できる。
詳細度の競合を減らす
WordPressのテーマ開発では、ブロックが出力するクラスとテーマの独自クラスが混在する。
ここにプラグインのCSS、追加CSS、ブロック設定から生成されるCSSが加わる。結果として、同じ要素に複数のルールが適用される。
特に問題になるのが詳細度の競合である。
- コアブロックの標準CSS
- テーマの
style.css - ブロック固有の生成CSS
- プラグインのCSS
- 投稿本文に保存されたインラインスタイル
- 管理画面の追加CSS
この順序や詳細度を把握しないままセレクターを追加すると、問題を解決するためにさらに強いセレクターが必要になる。最終的には!importantが増える。
theme.jsonは、WordPressのブロック設定とスタイル生成の仕組みに沿って定義する。これにより、独自CSSを後から強制するよりも、WordPressのスタイル処理と同じ経路で値を適用できる。
もちろん、theme.jsonですべての競合が消えるわけではない。既存テーマのCSSやプラグインの高詳細度セレクターが残っている場合、競合は継続する。
しかし、テーマ自身が不要なCSSを出力しなくなれば、競合の発生源は減る。修正すべき対象が限定されるため、原因調査の時間も短くなる。
CSSを完全に削除する設計ではない
theme.jsonを導入しても、style.cssが完全に不要になるわけではない。
複雑なアニメーション、疑似要素、特殊なレイアウト、外部ライブラリとの連携、テーマ固有の装飾にはCSSが必要になる。ブロックの標準設定だけでは表現できない要件もある。
適切な分担は次の通りである。
| 対象 | 主な管理場所 | 理由 |
|---|---|---|
| サイト全体の色 | theme.json | プリセットと共通値として管理できる |
| 基本の文字サイズ | theme.json | エディターとフロントエンドを一致させやすい |
| ブロックの余白 | theme.json | ブロック設定とスタイルを統合できる |
| ボタンやリンクの共通値 | theme.json | Elementsで横断的に適用できる |
| 複雑なアニメーション | CSS | JSONの設定だけでは表現しにくい |
| 疑似要素の装飾 | CSS | ブロック設定の対象外になりやすい |
| 外部ライブラリの上書き | CSS | 外部の出力仕様に依存する |
| JavaScript連動の状態表示 | CSSとJavaScript | 状態変更と見た目を分離する必要がある |
この境界を決めず、すべてをtheme.jsonへ移行しようとすると、設定ファイルが読みにくくなる。逆に、従来通りCSSですべてを管理すると、ブロックエディターとフロントエンドの差分が増える。
目的はCSSゼロではない。構造化できるスタイルをtheme.jsonへ移し、CSSでしか扱えない処理だけを残すことである。
CSSを減らすこと自体が目標になると、設定ファイルが別の巨大なCSSになる。減らすべき対象は記述量ではなく、重複と競合である。
ブロックテーマでの実装順序
theme.jsonによるWordPressテーマ開発では、ファイルを作って値を移すだけでは不十分である。既存のCSS、PHP、ブロック設定の責務を分解する必要がある。
まず既存のスタイルを分類する
最初に、現在のテーマで使われているCSSを分類する。
1. サイト全体に適用される基準値
2. HTML要素に共通するスタイル
3. 特定ブロックに固有のスタイル
4. ページやテンプレート限定のスタイル
5. 疑似要素やアニメーションなど、CSSに残すべき処理
6. プラグインや外部ライブラリに依存する上書き
この分類をせずに移行を始めると、同じ定義をtheme.jsonとCSSに残すことになる。どちらが正しい値なのかが不明になる。
特に、functions.phpにあるadd_theme_supportの扱いを明確にする必要がある。theme.jsonで置き換えられる設定と、PHPでしか処理できない設定は異なる。
次に共通値をプリセット化する
色、文字サイズ、余白など、複数の場所で利用する値をプリセットとして整理する。
このとき、値を増やしすぎないことが重要である。色が十数種類あり、文字サイズが細かく分かれていると、選択肢は増えるが、実際の運用では判断コストが上がる。
プリセットはデザインシステムの変数である。単なる色見本ではない。
例えば、同じ白色でも、本文背景用、カード背景用、反転表示用で役割が異なる場合がある。値だけでなく役割を基準に名前を付けると、後から変更しやすい。
Rootでサイト全体を固定する
プリセットを定義した後、Rootでサイト全体の基準を設定する。
ここで設定するのは、ページ全体の背景、本文の色、基本的な文字サイズ、行間、コンテンツ幅などである。
コンテンツ幅については、テーマのテンプレート構造と合わせて確認する必要がある。Root側で幅を設定しても、テンプレート側に別の幅指定があると、意図したレイアウトにならない。
ブロックテーマでは、テンプレート、テンプレートパーツ、theme.jsonの三つがレイアウトに関わる。スタイルだけを見ていると、幅の問題をCSSの問題と誤認する。
Elementsで横断的な要素を統一する
次に、リンク、ボタンなど、複数のブロックに登場する要素をElementsで管理する。
この段階で、各ブロックの個別CSSを確認する。Elementsで吸収できるルールがあれば、個別指定を削除する。
ただし、見た目が同じでも意味が異なる要素は分けるべきである。すべてのボタンを同じ見た目にする必要がない場合、Elementsに固定値を置くと、Blocks側での例外が増える。
共通化は多ければよいわけではない。変更単位が一致するものだけを共通化する。
Blocksでは差分だけを定義する
最後に、ブロック固有のスタイルをBlocksへ移す。
コードブロックの背景、引用の境界線、見出しの文字サイズなどが該当する。ここで共通値を繰り返さない。
ブロック単位の設定が増えた場合は、テーマのコンポーネント設計を見直す必要がある。たとえば、グループブロックに複数の役割を持たせ、すべてを個別設定で制御しているなら、ブロックパターンやスタイルバリエーションに分けた方がよい。
theme.jsonは、単体の設定ファイルではない。編集可能なコンポーネントの境界を決めるファイルでもある。
バージョン管理とWordPress 6.6以降の仕様
theme.jsonには仕様バージョンがある。現在の開発では、使用するWordPressのバージョンとtheme.jsonのversionを一致させる必要がある。
確認されている仕様の区分は次の通りである。
| 仕様バージョン | 対応するWordPress | 位置づけ |
|---|---|---|
| version 1 | WordPress 5.8で導入 | 初期仕様 |
| version 2 | WordPress 5.9から6.5で標準化 | ブロックテーマ開発の標準的な仕様 |
| version 3 | WordPress 6.6以降 | 新しい設定体系への対応 |
WordPress 6.6以降ではversion 3が導入された。ただし、WordPress 6.5以下の環境でversion 3が正常に動作すると考えてはいけない。
本番環境のWordPressが古い場合、開発環境だけを新しくしてtheme.jsonを作成すると、公開環境で設定が無視される可能性がある。特に、ローカル環境をDockerで構築している場合、イメージのタグと本番環境のバージョンに差が出やすい。
バージョン管理で確認する項目
テーマを配布する場合や複数環境で運用する場合は、次の項目を固定する。
- 本番環境のWordPressバージョン
- 開発環境のWordPressバージョン
theme.jsonのversion- 使用するブロック機能の対応状況
- プラグインが出力するブロックとの互換性
- 既存コンテンツに保存されたスタイルの扱い
theme.jsonの仕様だけを確認しても不十分である。テーマが利用するブロック、プラグイン、テンプレートの組み合わせで動作が決まる。
v2からv3への移行で見るべき点
仕様バージョンを上げる場合、単純に数字だけを変更してはいけない。
まず、対象となるWordPressで設定が認識されるかを確認する。次に、エディター画面のUIが変わっていないかを確認する。最後に、フロントエンドで生成されるCSSと既存CSSの優先順位を確認する。
移行時は、次の順序が安全である。
1. 本番環境と同じWordPressバージョンで検証環境を作る
2. 現行のtheme.jsonと生成CSSを保存する
3. 仕様バージョンを変更する
4. エディターで設定項目の表示を確認する
5. ブロックパターンと既存記事を確認する
6. ブラウザー上で生成されたCSSの差分を確認する
7. 問題がなければ本番環境へ反映する
ここでの検証対象は、トップページだけではない。記事本文、固定ページ、検索結果、404ページ、テンプレートパーツを確認する必要がある。
テーマ全体のスタイルは正しくても、古い記事に保存されたブロック属性が原因で表示が変わることがある。
既存CSSとの移行で発生するボトルネック
既存テーマへtheme.jsonを導入する場合、最大のボトルネックは設定の移行ではない。既存CSSとの二重管理である。
例えば、theme.jsonで段落の文字色を定義し、style.cssにも段落用の文字色が残っているとする。この場合、値が同じなら問題は見えない。しかし、片方だけ変更した時点で管理状態が分岐する。
移行作業では、CSSを次の三種類に分けるとよい。
移行対象になるCSS
サイト全体の色、文字サイズ、余白、ブロックの基本スタイルは、theme.jsonへ移行しやすい。
特に、同じ値が複数のセレクターで繰り返されている場合、移行の効果が大きい。共通値として定義できるため、重複が減る。
残すべきCSS
アニメーション、疑似要素、特殊なセレクター、複雑な状態変化はCSSに残す。
theme.jsonに対応する設定があるからといって、表現上の要件まで移行できるわけではない。移行できないものを無理にJSON化すると、設定の意味が読みにくくなる。
削除候補になるCSS
WordPressやブロックの標準機能と重複しているCSSは、削除候補である。
ただし、削除は最後に行う。先にCSSを消すと、どの設定が不足しているのかを切り分けにくい。
移行後にエディターとフロントエンドを確認し、theme.json側の設定が期待通りに反映されていることを確認してから削除する。
移行作業の単位はファイルではなく、スタイルの責務である。style.cssを一括削除しても、設計は改善しない。パフォーマンスと保守性をどう評価するか
theme.jsonを導入するとCSSの記述量は減る。しかし、パフォーマンス改善を自動的に保証するものではない。
WordPressが生成するCSSも、設定が増えれば大きくなる。プリセット、ブロックごとのスタイル、バリエーションを無制限に追加すると、出力されるルールも増える。
したがって、評価すべき指標はCSSファイルの行数だけではない。
- 同じ値が複数箇所に定義されていないか
- ブロックごとの例外が増えていないか
- 未使用のプリセットが残っていないか
- エディターとフロントエンドの表示が一致しているか
- 既存CSSとの詳細度競合が減っているか
- テーマ更新時に変更箇所を特定できるか
theme.jsonによるスタイル管理の効果は、ページの表示速度より保守性に現れやすい。CSSの総量が減っても、生成ルールが複雑なら調査コストは下がらない。
反対に、CSSの行数が大きく変わらなくても、色や余白の定義元が一つになれば、変更にかかる時間は短くなる。
検証は生成結果を見る
設定ファイルだけを読んで動作を判断するのは危険である。WordPressが実際に出力したHTMLとCSSを見る必要がある。
検証対象は次の通りである。
- エディター上の設定UI
- フロントエンドのHTML
- 出力されたCSSカスタムプロパティ
- ブロック固有のスタイル
- テーマの追加CSS
- プラグインが読み込むCSS
- モバイル幅でのレイアウト
- 保存済みコンテンツと新規コンテンツの差分
特に、エディターとフロントエンドの表示差分は見落とされやすい。エディターでは管理画面側のCSSが加わるため、公開画面とは異なる結果になる。
見た目が正しいかだけではなく、どのルールが適用されたかを確認する。開発者ツールで該当要素を選択し、適用済みルールと取り消し線になったルールを確認する。この作業で詳細度の競合箇所を特定できる。
theme.jsonを使わない方がよいケース
theme.jsonはブロックテーマと相性がよい。しかし、すべてのWordPressサイトで全面的に導入する必要はない。
既存のクラシックテーマを維持し、編集画面の自由度も必要としない場合、既存CSSを整理するだけで十分なことがある。大規模な移行には、テーマ構造、保存済みコンテンツ、プラグインの互換性確認が必要になる。
また、サイトのレイアウトが独自のPHPテンプレートとJavaScriptに強く依存している場合、theme.jsonだけで全体を管理しようとすると、設定と実装の境界が不自然になる。
導入の判断は、次の観点で行うべきである。
- ブロックエディターを主要な編集環境として使うか
- サイト全体のデザイン値を共通化したいか
- 編集者に許可する操作範囲を定義したいか
- ブロックテーマへ移行する予定があるか
- 既存CSSの詳細度競合が保守上の問題になっているか
これらが明確なら、theme.jsonは有効である。単に新しい形式を使いたいという理由だけで移行すると、運用コストが先に発生する。
WordPressテーマ設計としての結論
theme.jsonによるスタイル管理は、WordPressのブロックテーマ開発における基盤である。
Rootでサイト全体の基準を定義する。Elementsで横断的な要素を統一する。Blocksでブロック固有の差分だけを指定する。CSSは、JSON設定では表現できない処理に限定する。
この構造を守れば、スタイルの依存関係が追いやすくなる。CSSカスタムプロパティによって値を共通化できる。エディターとフロントエンドの設定差分も減る。結果として、テーマ更新時の確認範囲が狭くなる。
最後に、導入による変化を整理する。
- 改善点:色、余白、文字サイズなどの共通値を一元管理できる
- 改善点:ブロックエディターとフロントエンドの設定を一致させやすい
- 改善点:CSSの重複と詳細度競合を減らせる
- トレードオフ:WordPressのバージョン管理が必要になる
- トレードオフ:既存CSSとの二重管理が移行時のボトルネックになる
- トレードオフ:複雑な装飾や特殊なレイアウトはCSSに残る
- 判断基準:CSSの行数ではなく、変更時の依存関係と検証範囲で評価する
theme.jsonはCSSの代替ではない。WordPressが提供するブロック、エディター、テーマ設定を同じ設計に接続するための定義ファイルである。
したがって、導入時に見るべきなのは記述量の削減率ではない。どの値をどこで管理し、どのブロックが例外を持ち、どのCSSを残すのか。その境界が明確になっているかである。
Related reading: theme.jsonとカスタムCSSの競合:ブロックテーマ開発で破綻しないスタイル優先順位の設計ルール and WordPressの自作プラグインとfunctions.phpの境界線:機能の肥大化を防ぐ設計ルール.