MENU

問い合わせ


    【WordPressで作るキュレーションメディア 第1回】theme.json でデザイントークンを定義する(子テーマの基本)

    WordPress のサイトで「リンクの色を少し変えたい」と頼んだら、CSS のあちこちに上書きが増えていき、次の担当者がどこを直せばよいか分からなくなった。長く運用するメディアでよく起きる状況です。

    「サイトの色や文字の大きさを、担当者が変わっても同じルールで管理できるようにしたい。WordPress ではどこに書くのが正解?」

    結論から言うと、ブロックテーマでは、色・文字サイズ・余白といったデザインの基本ルールを theme.json に集約するのが基本です。theme.json に書いた値は「デザイントークン(=色や余白などに名前を付けて共通化した値)」として、テンプレート・パターン・管理画面の「スタイル」画面のすべてから同じ名前で参照されます。

    前回の第0回では、Docker で WordPress 6.8 と子テーマ・プラグインの空の雛形を用意しました。第1回の今回は、子テーマ curation-child の theme.json にデザイントークンを定義し、ダーク配色のスタイルバリエーションを1つ追加します。

    目次

    theme.json とデザイントークンの仕組み

    theme.json は、ブロックテーマの「設定(settings)」と「スタイル(styles)」を1つの JSON ファイルで定義する仕組みです。

    区分役割今回定義するもの
    settingsエディターで選べる値の一覧(プリセット)と、使える機能のオン・オフ色パレット、フォント、文字サイズ、余白スケール、コンテンツ幅
    stylesサイト全体・要素・ブロックに実際に適用する見た目本文の色と書体、見出し、リンク、ボタン、コードブロック

    📰 出典:WordPress Theme Handbook「Global Settings & Styles (theme.json)」

    settings に定義したプリセットは、WordPress が CSS のカスタムプロパティ(=CSS の変数)として出力します。たとえば色パレットに brand を定義すると、ページに --wp--preset--color--brand が出力され、ブロックの色指定やパターンからこの名前で参照できます。

    子テーマの theme.json は親テーマに「重ねて」読み込まれる

    子テーマの theme.json は、親テーマ(Twenty Twenty-Five)の theme.json に重ねて読み込まれます。子テーマに書いた項目だけが上書きされ、書いていない項目は親の値がそのまま使われます。

    ただし注意点があります。色パレットや文字サイズのようなプリセットの一覧は、項目単位ではなく一覧ごと置き換わります。子テーマでパレットを定義すると、親テーマのパレットは使われなくなります。

    親テーマのテンプレートやパターンは、base・contrast・accent-1〜accent-6 という色の名前や、20〜80 という余白の名前を参照しています。これらの名前を消すと、親テーマの部品の見た目が崩れます。そこで今回は、親テーマと同じ名前は残して値だけを変え、メディアに必要な名前(ブランド色・PR表記の色)を追加する方針にしました。

    子テーマの theme.json を書く

    ここから実装です。今回変更・追加したファイルは次のとおりです。

    ファイル変更内容
    wp-content/themes/curation-child/theme.json色・フォント・文字サイズ・余白・レイアウトと、要素のスタイルを定義
    wp-content/themes/curation-child/styles/dark.jsonスタイルバリエーション「ダーク」を追加
    wp-content/themes/curation-child/style.csstheme.json で書けない2点を追加、バージョンを 0.2.0 に

    色パレット:役割で名前を付ける

    wp-content/themes/curation-child/theme.json(settings.color 部分)

    "color": {
    	"defaultPalette": false,
    	"defaultGradients": false,
    	"defaultDuotone": false,
    	"palette": [
    		{ "slug": "base", "name": "背景", "color": "#FFFFFF" },
    		{ "slug": "contrast", "name": "本文", "color": "#1F2328" },
    		{ "slug": "brand", "name": "ブランド(リンク・ボタン)", "color": "#1A5FB4" },
    		{ "slug": "notice", "name": "注意・PR表記の文字", "color": "#8A5300" },
    		{ "slug": "notice-bg", "name": "注意・PR表記の背景", "color": "#FFF4E0" },
    		{ "slug": "accent-1", "name": "淡い青(引用元・補足の背景)", "color": "#E8F0FB" },
    		{ "slug": "accent-2", "name": "淡い橙", "color": "#FFF4E0" },
    		{ "slug": "accent-3", "name": "濃い青", "color": "#1A5FB4" },
    		{ "slug": "accent-4", "name": "補足テキスト(日付・出典)", "color": "#5F6670" },
    		{ "slug": "accent-5", "name": "淡い灰(区切りの背景)", "color": "#F6F7F9" },
    		{ "slug": "accent-6", "name": "罫線", "color": "color-mix(in srgb, currentColor 20%, transparent)" }
    	]
    }

    ポイントは次の3つです。

    • 名前(slug)は色味ではなく役割で付ける:blue ではなく brand、orange ではなく notice にしておけば、後でブランドカラーを変えても名前を変える必要がありません。
    • name は日本語にする:エディターの色選択に表示されるのは name です。編集者が迷わないよう、用途が分かる名前にしています。
    • defaultPalette: false:WordPress 標準の色(赤・緑など)を選択肢から外し、決めた色以外を使いにくくします。

    文字色と背景色の組み合わせは、コントラスト比(=明るさの差の比率)が 4.5:1 以上になるように選びました。WCAG 2.1 の達成基準 1.4.3(レベルAA)で、通常サイズの文字に求められる値です。今回の組み合わせは、本文が約15.8:1、ブランド色のリンクが約6.3:1、PR表記の文字と背景が約5.8:1 です。

    📰 出典:W3C「Understanding Success Criterion 1.4.3: Contrast (Minimum)」

    フォントと文字サイズ:日本語の本文を読みやすくする

    wp-content/themes/curation-child/theme.json(settings.typography 部分)

    "typography": {
    	"defaultFontSizes": false,
    	"fluid": true,
    	"fontFamilies": [
    		{
    			"slug": "system-ja",
    			"name": "日本語システムフォント",
    			"fontFamily": "-apple-system, BlinkMacSystemFont, \"Hiragino Sans\", \"Hiragino Kaku Gothic ProN\", \"Noto Sans JP\", Meiryo, sans-serif"
    		},
    		{
    			"slug": "monospace",
    			"name": "等幅",
    			"fontFamily": "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
    		}
    	],
    	"fontSizes": [
    		{ "slug": "small", "name": "小", "size": "0.875rem", "fluid": false },
    		{ "slug": "medium", "name": "本文", "size": "1rem", "fluid": { "min": "1rem", "max": "1.0625rem" } },
    		{ "slug": "large", "name": "大", "size": "1.25rem", "fluid": { "min": "1.125rem", "max": "1.25rem" } },
    		{ "slug": "x-large", "name": "特大", "size": "1.5rem", "fluid": { "min": "1.375rem", "max": "1.625rem" } },
    		{ "slug": "xx-large", "name": "見出し1", "size": "2rem", "fluid": { "min": "1.625rem", "max": "2.25rem" } }
    	]
    }

    親テーマの標準フォント(Manrope)は欧文用のため、日本語の文字は OS のフォントで表示されます。そこで、端末に入っている日本語フォントを順に指定する「システムフォント」の一覧に置き換えました。Web フォントを読み込まないので、表示速度の面でも有利です。

    文字サイズは親テーマと同じ名前(small〜xx-large)のまま、日本語の記事向けに見出しを少し小さめにしています。fluid を指定すると、画面幅に応じて min から max の間でサイズが自動的に変わります(CSS の clamp() で出力されます)。

    余白スケールとコンテンツ幅

    wp-content/themes/curation-child/theme.json(settings.spacing と layout 部分)

    "spacing": {
    	"defaultSpacingSizes": false,
    	"units": [ "px", "em", "rem", "%", "vw", "vh" ],
    	"spacingSizes": [
    		{ "slug": "10", "name": "1(最小)", "size": "0.25rem" },
    		{ "slug": "20", "name": "2", "size": "0.5rem" },
    		{ "slug": "30", "name": "3", "size": "1rem" },
    		{ "slug": "40", "name": "4", "size": "1.5rem" },
    		{ "slug": "50", "name": "5", "size": "clamp(1.5rem, 4vw, 2.5rem)" },
    		{ "slug": "60", "name": "6", "size": "clamp(2rem, 6vw, 4rem)" },
    		{ "slug": "70", "name": "7", "size": "clamp(3rem, 7vw, 5rem)" },
    		{ "slug": "80", "name": "8(最大)", "size": "clamp(4rem, 9vw, 7rem)" }
    	]
    },
    "layout": {
    	"contentSize": "720px",
    	"wideSize": "1200px"
    }

    余白は「8段階から選ぶ」ルールにしています。書き手や制作者が自由な数値を入れると、ページごとに余白がばらつきます。段階を決めておけば、エディターのスライダーもこの8段階で動きます。

    📰 出典:WordPress Theme Handbook「Spacing」

    contentSize(本文の幅)は 720px にしました。16px の文字なら1行はおよそ40〜45文字で、PC の広い画面でも1行が長くなりすぎないようにしています。wideSize は「幅広」配置のブロック(比較表など)に使う最大幅です。

    styles:本文・見出し・リンク・ボタンの見た目

    wp-content/themes/curation-child/theme.json(styles 部分・抜粋)

    "styles": {
    	"color": {
    		"background": "var:preset|color|base",
    		"text": "var:preset|color|contrast"
    	},
    	"typography": {
    		"fontFamily": "var:preset|font-family|system-ja",
    		"fontSize": "var:preset|font-size|medium",
    		"fontWeight": "400",
    		"letterSpacing": "0.02em",
    		"lineHeight": "1.8"
    	},
    	"elements": {
    		"heading": {
    			"typography": { "fontWeight": "700", "lineHeight": "1.4", "letterSpacing": "0" }
    		},
    		"h2": {
    			"typography": { "fontSize": "var:preset|font-size|x-large" },
    			"spacing": { "margin": { "top": "var:preset|spacing|60" } }
    		},
    		"link": {
    			"color": { "text": "var:preset|color|brand" },
    			"typography": { "textDecoration": "underline" },
    			":hover": { "typography": { "textDecoration": "none" } }
    		},
    		"button": {
    			"color": { "background": "var:preset|color|brand", "text": "var:preset|color|base" },
    			"border": { "radius": "4px" },
    			":hover": {
    				"color": { "background": "var:preset|color|contrast", "text": "var:preset|color|base" }
    			}
    		}
    	},
    	"blocks": {
    		"core/code": {
    			"typography": { "fontFamily": "var:preset|font-family|monospace" }
    		},
    		"core/post-date": {
    			"color": { "text": "var:preset|color|accent-4" }
    		}
    	}
    }

    styles では、値を直接書かずに var:preset|color|brand のようにプリセットの名前で参照しています。これが「トークンを使う」ということです。ブランド色を変えたいときは、パレットの1か所を直せばリンクもボタンも一緒に変わります。

    リンクには下線を付けたままにしています。色だけでリンクを区別すると、色の見分けにくい人には分かりにくいためです。core/code の書体を等幅に変えているのは、親テーマがコードブロックに指定していた書体(Fira Code)を、パレットと同じ理由で一覧ごと置き換えたためです。

    📰 出典:Block Editor Handbook「Theme.json Reference(Version 3)」

    スタイルバリエーション「ダーク」を追加する

    スタイルバリエーションは、theme.json の一部を差し替える「着せ替え」の仕組みです。子テーマの styles/ フォルダに JSON を置くと、管理画面「外観 > エディター > スタイル」に選択肢として表示されます。

    wp-content/themes/curation-child/styles/dark.json(抜粋)

    {
    	"$schema": "https://schemas.wp.org/wp/6.8/theme.json",
    	"version": 3,
    	"title": "ダーク",
    	"settings": {
    		"color": {
    			"palette": [
    				{ "slug": "base", "name": "背景", "color": "#14181F" },
    				{ "slug": "contrast", "name": "本文", "color": "#E6E8EB" },
    				{ "slug": "brand", "name": "ブランド(リンク・ボタン)", "color": "#8AB4F8" },
    				{ "slug": "notice", "name": "注意・PR表記の文字", "color": "#F5C26B" },
    				{ "slug": "notice-bg", "name": "注意・PR表記の背景", "color": "#3A2C12" }
    			]
    		}
    	}
    }

    (実ファイルでは accent-1〜accent-6 も同じ名前で定義しています)

    バリエーションでは、同じ名前のまま値だけを変えます。本文もボタンも名前で色を参照しているので、パレットを差し替えるだけで全体の配色が切り替わります。名前を変えてしまうと、参照している箇所が色を失います。

    📰 出典:WordPress Theme Handbook「Style Variations」

    style.css には theme.json で書けないものだけを書く

    wp-content/themes/curation-child/style.css(追加部分)

    /* リンクの下線を文字から少し離して読みやすくする(theme.json では指定できない) */
    a {
    	text-underline-offset: 0.2em;
    }
    
    /* キーボード操作時のフォーカス位置を分かりやすくする */
    :where(.wp-site-blocks) :focus-visible {
    	outline: 2px solid var(--wp--preset--color--brand);
    	outline-offset: 2px;
    }

    CSS の中でも色は var(--wp--preset--color--brand) のようにトークンを参照します。こうしておけば、ダーク配色に切り替えたときもフォーカス枠の色が自動で変わります。あわせて style.css のヘッダーの Version を 0.2.0 に上げました。この値は CSS の URL の ?ver= に付くため、ブラウザに古い CSS が残るのを防げます。

    動作確認の方法

    第0回と同じ手順で起動し、次の点を確認します(筆者の環境で確認済みです)。

    docker compose up -d
    ./scripts/setup.sh
    
    # 追加したパレットの CSS 変数が出力されているか
    curl -s http://localhost:8088/ | grep -o 'wp--preset--color--[a-z0-9-]*' | sort -u
    
    # theme.json の構文エラーがなく、テーマ情報を読めるか
    docker compose run --rm wpcli wp theme get curation-child --fields=name,version,template,status
    • 出力に wp--preset--color--brand・notice・notice-bg が含まれる
    • wp theme get がエラーなく version 0.2.0 を返す
    • 管理画面「外観 > エディター > スタイル」で、パレットに日本語名の色が並び、スタイルの一覧に「ダーク」が表示される。「ダーク」を選んで保存すると、トップページの --wp--preset--color--base が #14181F に変わる

    筆者は「ダーク」の適用を、REST API(グローバルスタイルのエンドポイント)経由で保存し、CSS 変数が切り替わることでも確認しました。

    つまずきやすい点

    • 標準の色の CSS 変数も出力される:defaultPalette: false はエディターの選択肢から外す設定で、--wp--preset--color--black などの CSS 変数自体は出力され続けます。「使わせない」ための設定だと理解しておきます。
    • 親テーマのスタイルバリエーションも一覧に出る:WordPress 6.8 では、子テーマの styles/ に加えて親テーマのバリエーション(Evening、Noon など)も一覧に表示されます。これらは親テーマ用の配色なので、選ぶとメディアの配色ルールから外れます。「サイト全体のスタイルは管理者だけが変更する」という運用ルールを決めておきましょう。なお、親と同じファイル名のバリエーションを子テーマに置くと、子テーマ側だけが表示されます。
    • 管理画面での変更が theme.json より優先される:「スタイル」画面で保存した内容はデータベースに保存され、theme.json の値を上書きします。theme.json を直しても表示が変わらないときは、「スタイル」画面の変更履歴やリセットを確認してください。
    • JSON の構文エラー:カンマの付け忘れ一つで theme.json 全体が読み込まれなくなります。$schema を書いておくと、対応したエディターで入力補完とエラー表示が使えます。

    発注者向けメモ:デザインのルールを「1か所」に置く

    theme.json にデザインのルールを集約すると、担当者が変わっても「色を変えるならここ」という場所が1つに決まります。逆に、CSS の個別の上書きが増えるほど、1つの修正で思わぬ場所の見た目が変わる、確認箇所が増える、といった形で保守の工数が上がります。

    開発会社に依頼するときは、次の点を確認しておくと安心です。

    • 色・文字サイズ・余白の一覧(デザイントークン)を納品物に含めるか:デザインカンプとあわせて、名前と用途の一覧があると後の修正依頼が伝えやすくなります。
    • 管理画面の「スタイル」を誰が触ってよいか:画面から変更できる範囲が広いぶん、ルール外の変更も簡単にできてしまいます。
    • アクセシビリティの基準:文字と背景のコントラスト比など、どの基準を目安にするかを最初に合意します。
    • ダークモードなどの切り替えは本当に必要か:バリエーションを1つ増やすごとに、全ページでの表示確認が必要になります。

    打ち合わせでは、次のように聞いてみてください。

    • 「色や余白の指定は theme.json にまとめますか?CSS で個別に上書きしている箇所はどのくらいありますか?」
    • 「管理画面から変更された見た目を、コードの状態に戻す手順はありますか?」
    • 「文字と背景のコントラスト比は確認していますか?どの基準を使っていますか?」

    まとめと次回予告

    第1回では、子テーマの theme.json にデザイントークンを定義しました。

    • theme.json の settings でプリセット(色・フォント・文字サイズ・余白)を定義し、styles から名前で参照する
    • 子テーマのプリセットは一覧ごと置き換わるため、親テーマが使う名前(base、accent-1、50 など)は残して値だけ変える
    • スタイルバリエーションは同じ名前のまま値を変えるだけで配色を切り替えられる
    • style.css には theme.json で書けないものだけを書き、色はトークンで参照する

    次回は「カテゴリ・タグ・「特集」― タクソノミー設計」です。記事の分類をカテゴリ・タグ・特集の3つに分け、プラグインで「特集」タクソノミーを登録します。

    この連載の記事一覧

    この記事は連載「WordPressで作るキュレーションメディア」の1回です。連載のほかの回は次のとおりです(連載の一覧ページ)。

    システム制作・運用・保守のお問い合わせはこちら


      よかったらシェアしてね!
      • URLをコピーしました!
      • URLをコピーしました!

      この記事を書いた人

      株式会社THIRD HERO代表取締役 朝野貴朗
      Webシステム開発を中心に、toC向けサービスサイトの運営、ツール開発などを行ってまいりました。

      コメント

      コメント一覧 (1件)

      目次