WordPressのオリジナルテーマをSCSSで自作する|デザイントークン設計と実装

2026.07.08 約 13 分で読めます
WordPressのオリジナルテーマ制作を表すアイキャッチ。ノートに描いたデザイントークンのパレットからヘッダー・カード・ボタンのUI部品へ線がつながる俯瞰イラスト

アクセント色をほんの少し濃くしたい。それだけのことで、CSSの何十箇所を書き換えるはめになりました。既製テーマを離れて自分でテーマを作り始めた頃の話です。今は色も余白も「トークン」として1箇所にまとめ、そこを直せば全体が一斉に変わります。このブログのオリジナルテーマで実際に使っている設計を、実コードごと公開します。

結論:先にデザイントークンを決めると、オリジナルテーマは壊れない

作る順番を1つ変えるだけです。テンプレートから書き始めず、先に色・余白・文字サイズを「変数(デザイントークン)」として決める。あとは各パーツがその変数を参照するだけにします。こうしておくと、デザインの調整が1ファイルの書き換えで済みます。テーマが育っても破綻しにくい、というのが何度もCSSを書き直した末の結論でした。

全体像はこの1枚です。源が1つ、参照する先がたくさん、という形にします。

デザイントークンの一元管理を示す図。_variables.scssの1つの源から、ヘッダー・記事カード・ボタン・CTAがvar()で色や余白を参照する構造
トークンは1つの源。各コンポーネントは var() で参照するだけにする

デザイントークンとは(色・余白・文字を「変数」にする)

デザイントークンは、色や余白や文字サイズといったデザインの最小単位に名前を付けたものです。#12abb1 という値に --color-dev という名前を与えて、CSS側では色コードを直書きせず名前で呼ぶ。名前で呼んでおけば、後から中身を差し替えても呼び出し側は無傷です。

SCSSの変数($color)ではなくCSSカスタムプロパティ(--color)を選んだ理由もあります。カスタムプロパティはブラウザに値が残るので、開発者ツールで確認でき、メディアクエリやダークモードで上書きするのも簡単でした。ここは好みが分かれるところですが、わたしは実行時に効くほうを取りました。

実装①:_variables.scss にトークンを定義する

オリジナルテーマの土台として、まず :root にトークンを並べます。本番で使っているものから抜粋します。

:root {
  /* 色:ベース + アクセント(ティール)+ アンバー */
  --color-bg:      #f3f8f9;
  --color-text:    #1e1b18;
  --color-dev:     #12abb1;   /* アクセント */
  --color-dev-dark:#0f7f85;
  --color-biz:     #c2862a;

  /* タイポグラフィ */
  --font-base:    'Noto Sans JP', sans-serif;
  --font-display: 'Shippori Mincho B1', 'Noto Serif JP', serif;
  --text-base: 1rem;
  --text-2xl:  1.5rem;

  /* スペーシング(4px 基準で刻む) */
  --sp-2: 0.5rem;  --sp-4: 1rem;  --sp-8: 2rem;  --sp-12: 3rem;

  /* レイアウト幅・角丸・影 */
  --width-article: 760px;
  --radius-xl: 14px;
  --shadow-md: 0 4px 16px rgba(30,27,24,.09);
}

ポイントは、スペーシングを4px基準の飛び番で持つことです。--sp-4 が1rem(16px)で、そこから 2 / 8 / 12 と刻む。余白の値を毎回「なんとなく18px」で置かず、決めた刻みから選ぶだけにすると、画面全体のリズムがそろいました。使う側はこう書きます。

.cta-neoriva {
  padding: var(--sp-8);
  border: 1px solid var(--color-dev);
  border-radius: var(--radius-xl);
}

実装②:ビルドは Dart Sass + PostCSS(Gulpは使わない)

ビルド環境は、できるだけ薄くしました。Gulpも古い node-sass も入れません。Dart Sass の sass コマンドと、圧縮用の PostCSS(cssnano)だけです。package.json はこれだけ。

"scripts": {
  "build": "sass assets/scss/main.scss assets/css/main.css --style=expanded && postcss assets/css/main.css --use cssnano -o assets/css/main.min.css --no-map",
  "watch": "sass --watch assets/scss/main.scss assets/css/main.css"
},
"devDependencies": {
  "sass": "^1.77.0", "postcss": "^8.4.0", "postcss-cli": "^11.0.0", "cssnano": "^7.0.0"
}

部分ファイルは main.scss@use で束ねます。かつての @import は非推奨になったので、今は @use です。

// main.scss
@use 'variables';
@use 'reset';
@use 'typography';
@use 'header';
@use 'single';
@use 'cta';
// … 全12本の部分ファイルを束ねる

実際にビルドしてみると、npm run build約4.4秒。12本・合計1,960行のSCSSが1枚のCSSにまとまり、41.1KB の展開版から 34.5KB の圧縮版になりました(15.9%減)。CSS変数を多用すると値がそのまま残るので、圧縮率は控えめです。ここは想定どおりでした。

自作クラシックテーマの構成図。functions.phpは薄くinc/に機能分割、assets/scssをmain.scssで@use束ね、npm run buildでmain.min.cssに変換してenqueueする流れ
機能は inc/、見た目は SCSS。functions.php は require するだけの薄い入口にする

実装③:functions.php を薄くして inc/ に分割する

機能を全部 functions.php に書くと、すぐに数百行の迷路になります。入口は薄くして、役割ごとに inc/ へ逃がしました。

<?php // functions.php は require するだけ
require get_template_directory() . '/inc/setup.php';    // テーマサポート・メニュー
require get_template_directory() . '/inc/enqueue.php';  // CSS/JS・フォント
require get_template_directory() . '/inc/helpers.php';  // 読了時間などの関数
require get_template_directory() . '/inc/security.php';
require get_template_directory() . '/inc/analytics.php';

CSSの読み込みは enqueue.php にまとめます。テーマのバージョンをクエリに付けておくと、更新時のキャッシュ切れも自動でそろう仕掛けです。

add_action( 'wp_enqueue_scripts', function () {
    $ver = wp_get_theme()->get( 'Version' );
    wp_enqueue_style( 'koma-ai-style',
        get_template_directory_uri() . '/assets/css/main.min.css', [], $ver );
} );

読了時間のような小さなロジックも helpers.php に置いておくと、テンプレート側は koma_reading_time() と呼ぶだけで済みます。日本語は400字/分でざっくり計算しています。

実装④:テンプレート階層と共通パーツ

あとはWordPressのテンプレート階層に乗せるだけです。トップは front-page.php、記事は single.php、カテゴリーは category.php。繰り返し使う部品は template-parts/ に切り出し、get_template_part() で呼びます。記事カードも記事末尾CTAも、この共通パーツ方式です。

<?php // single.php の一部
the_content();
get_template_part( 'template-parts/cta-neoriva' ); // 全記事共通のCTA

このCTAをテーマに組み込んだ話は記事末尾CTAをテーマに組み込む記事で詳しく書いています。

トークン運用でラクになった実例

効果が一番はっきり出たのは、色の微調整でした。アクセントのティールを少し濃くしたいとき、直したのは --color-dev の1行だけ。ヘッダー、記事カードの枠、ボタン、CTAの境界線が、同時に新しい色になりました。以前なら各セレクタを検索して1つずつ直していた作業が、まるごと消えます。

余白も同じです。記事の行間が少し詰まって見えたとき、触るのは --leading-normal--sp-* の刻み。個別ページのCSSを漁らずに、サイト全体のリズムを一括で調整できました。地味ですが、これが一番効きます。

この作り方が向かない場合

もちろん万能ではありません。合わない場面もあります。

  • ブロックテーマ(FSE)で作りたい:色やフォントの管理は theme.json が主役です。今回のクラシックテーマ + SCSS とは設計の前提が変わります
  • コードを書きたくない:SWELLなどの高機能な既製テーマのほうが、確実で速いです。無理に自作する場面ではありません
  • 短命なキャンペーンサイト:使い捨てるなら、設計にこだわる時間はもったいないかもしれません

逆に、長く運用する自分のサイトを細部までコントロールしたい人に、オリジナルテーマは向いています。同じテーマで多層防御を実装した話はWordPressのセキュリティ対策の記事に、ほかの実装は爆速開発・環境構築のカテゴリにまとめています。

まとめ

  • オリジナルテーマは、テンプレートより先にデザイントークン(色・余白・文字)を決める
  • トークンは _variables.scss:root にCSSカスタムプロパティで定義し、各パーツは var() で参照する
  • ビルドは Dart Sass + PostCSS の最小構成。Gulp も node-sass も要らない(実測ビルド4.4秒・12本1,960行→34.5KB)
  • functions.php は薄く、機能は inc/、部品は template-parts/ に分ける
  • ブロックテーマや使い捨てサイトには向かない。長く運用する自分のサイト向き

テーマの設計は、最初のひと手間で後の運用が驚くほどラクになります。こうした保守しやすいサイトを企業向けに設計・構築する仕事は、運営元のNEORIVAでも承っています。既製テーマの限界を感じ始めた方は、気軽に相談してください。参考にした公式ドキュメントは テンプレート階層Sass の @useCSSカスタムプロパティ(MDN) です。

こま

こま

元SE × AI開発 × 業務自動化の実践者

SE 4年 + プログラミング歴 8年。業務自動化と AI 組み込み開発を仕事にしながら、現場で使えるものだけを書いています。 最新のAIの現場を発信中!!