2026年9月28日
2026年9月28日
WordPressのカスタマイザーAPIの使い方:設定項目の追加からライブプレビュー・安全な出力まで
カスタマイザー API を使うと、「外観 → カスタマイズ」の画面に独自の設定項目を追加し、サイト運営者がプレビューを見ながら文言や色を変えられるようにできます。この記事では、セクション・セッティング・コントロールの関係を整理したうえで、テキスト・チェックボックス・色・選択肢の4種類の項目を追加し、テンプレートへ安全に出力する方法、再読み込みなしでプレビューに反映させる方法、ブロックテーマとの関係までを説明します。
カスタマイザーの3つの部品
カスタマイザー API は、役割の異なる3つの部品を組み合わせて使います。ここを混同すると、「項目は出たのに保存されない」といったつまずきにつながります。
- セクション(section):画面左側に並ぶ見出しのまとまりです。複数のセクションをさらに束ねるパネル(panel)もあります。
- セッティング(setting):保存される値そのものです。初期値、保存形式、サニタイズ方法、プレビューへの反映方法を決めます。
- コントロール(control):セッティングを編集するための入力欄です。テキスト欄、チェックボックス、カラーピッカーなどがあります。
コントロールは表示されるだけで、値を保存するのはセッティングです。セッティングを登録せずにコントロールだけを足しても、何も保存されません。
作業前の準備
コードは子テーマの functions.php、またはテーマの機能として配布するなら inc/customizer.php のような別ファイルに書いて読み込みます。親テーマを直接編集すると、テーマの更新で消えます。テーマの機能ではなくサイト固有の設定として持たせたい場合は、プラグインに置く方法もあります。
作業はステージング環境で行い、本番に反映する前にバックアップを取ってください。PHP の構文エラーで画面が真っ白になった場合は、FTP などで追記したファイルを元に戻せば復旧できます。
設定項目を追加する
告知バーの文言・表示の有無・アクセントカラー・サイドバーの位置を追加する例です。
add_action( 'customize_register', function ( WP_Customize_Manager $wp_customize ) {
$wp_customize->add_section(
'mytheme_options',
array(
'title' => 'テーマ設定',
'priority' => 30,
)
);
// 告知バーの文言(プレビューは部分更新)
$wp_customize->add_setting(
'mytheme_notice_text',
array(
'type' => 'theme_mod',
'default' => '',
'capability' => 'edit_theme_options',
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_text_field',
)
);
$wp_customize->add_control(
'mytheme_notice_text',
array(
'label' => '告知バーの文言',
'section' => 'mytheme_options',
'type' => 'text',
)
);
// 告知バーの表示
$wp_customize->add_setting(
'mytheme_show_notice',
array(
'default' => false,
'sanitize_callback' => 'mytheme_sanitize_checkbox',
)
);
$wp_customize->add_control(
'mytheme_show_notice',
array(
'label' => '告知バーを表示する',
'section' => 'mytheme_options',
'type' => 'checkbox',
)
);
// アクセントカラー(プレビューはJavaScriptで反映)
$wp_customize->add_setting(
'mytheme_accent_color',
array(
'default' => '#0b6bcb',
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_hex_color',
)
);
$wp_customize->add_control(
new WP_Customize_Color_Control(
$wp_customize,
'mytheme_accent_color',
array(
'label' => 'アクセントカラー',
'section' => 'mytheme_options',
)
)
);
// サイドバーの位置
$wp_customize->add_setting(
'mytheme_layout',
array(
'default' => 'right',
'sanitize_callback' => 'mytheme_sanitize_select',
)
);
$wp_customize->add_control(
'mytheme_layout',
array(
'label' => 'サイドバーの位置',
'section' => 'mytheme_options',
'type' => 'select',
'choices' => array(
'right' => '右',
'left' => '左',
'none' => '表示しない',
),
)
);
// 告知バーの文言を部分更新の対象にする
$wp_customize->selective_refresh->add_partial(
'mytheme_notice_text',
array(
'selector' => '.site-notice__text',
'render_callback' => function () {
return esc_html( get_theme_mod( 'mytheme_notice_text', '' ) );
},
)
);
} );
function mytheme_sanitize_checkbox( $checked ) {
return ! empty( $checked );
}
function mytheme_sanitize_select( $input, $setting ) {
$input = sanitize_key( $input );
$choices = $setting->manager->get_control( $setting->id )->choices;
return array_key_exists( $input, $choices ) ? $input : $setting->default;
}
セッティングの引数で、特に意識したいものを説明します。
- **
type**:theme_mod(既定)はテーマごとに保存され、optionはテーマに関係なくwp_optionsに保存されます。テーマを切り替えても残したい値はoptionが向いています。 - **
capability**:保存できる権限です。既定はedit_theme_optionsで、通常は変える必要がありません。 - **
sanitize_callback**:保存前に値を整える関数です。省略すると入力がそのまま保存されるため、項目ごとに指定してください。色はsanitize_hex_color、文字列はsanitize_text_field、数値はabsint、URL はesc_url_rawが基本です。選択肢は、上の例のように登録済みの選択肢と照合して、想定外の値なら初期値に戻します。 - **
transport**:refresh(既定)はプレビュー全体を再読み込みし、postMessageは再読み込みせずに部分的に反映します。
特定のページでだけ項目を出したいときは、コントロールに active_callback(例:'active_callback' => 'is_front_page')を指定できます。
テンプレートへ出力する
<?php if ( get_theme_mod( 'mytheme_show_notice', false ) ) : ?>
<div class="site-notice">
<span class="site-notice__text"><?php echo esc_html( get_theme_mod( 'mytheme_notice_text', '' ) ); ?></span>
</div>
<?php endif; ?>
保存時にサニタイズしていても、出力時のエスケープは省かないでください。保存処理を後から変えた場合や、データベースが別の経路で書き換えられた場合の備えになります。
もう1つの落とし穴は初期値です。add_setting() の default はカスタマイザー画面の中で使われる値で、get_theme_mod() には自動で引き継がれません。運営者が一度も保存していない状態でも正しく表示されるよう、get_theme_mod() の第2引数にも同じ初期値を渡します。初期値は定数や関数にまとめておくと、2か所で値がずれるのを防げます。
色の設定は、CSS 変数として出力するとテーマの CSS 側で扱いやすくなります。
add_action( 'wp_enqueue_scripts', function () {
$color = sanitize_hex_color( get_theme_mod( 'mytheme_accent_color', '#0b6bcb' ) );
if ( ! $color ) {
return;
}
// 'mytheme-style' は、テーマのスタイルシートを読み込むときのハンドル名に合わせる
wp_add_inline_style( 'mytheme-style', ':root{--mytheme-accent:' . $color . ';}' );
}, 20 );
wp_head で <style> を直接出力するより、wp_add_inline_style() で既存のスタイルシートに紐づけるほうが、読み込み順の管理がしやすくなります。
プレビューに即時反映させる
transport を postMessage にしたセッティングは、再読み込みの代わりに次のどちらかでプレビューを更新します。
部分更新(selective refresh):上のコードの add_partial() がこれにあたります。値が変わると、サーバー側で render_callback が実行され、selector に一致する要素の中身だけが置き換わります。PHP の出力をそのまま使えるため、表示ロジックを JavaScript で書き直す必要がありません。
JavaScript で直接反映:色のように、CSS の値を変えるだけで済むものに向いています。
// js/customizer-preview.js
( function ( api ) {
api( 'mytheme_accent_color', function ( value ) {
value.bind( function ( to ) {
document.documentElement.style.setProperty( '--mytheme-accent', to );
} );
} );
} )( wp.customize );
add_action( 'customize_preview_init', function () {
wp_enqueue_script(
'mytheme-customizer-preview',
get_stylesheet_directory_uri() . '/js/customizer-preview.js',
array( 'customize-preview' ),
'1.0.0',
true
);
} );
子テーマにファイルを置く場合は、get_template_directory_uri() ではなく get_stylesheet_directory_uri() を使います。前者は親テーマのフォルダを指すため、ファイルが見つからずに何も起きません。
子テーマ・ブロックテーマとの関係
theme_mod の値はテーマごとに保存されます。親テーマで設定していた値は、子テーマに切り替えると引き継がれません。子テーマへの移行時は、カスタマイザーでの設定をやり直すか、テーマのエクスポート・インポートができるプラグインで移すことを想定しておいてください。
ブロックテーマ(Twenty Twenty-Five など)では、見た目の調整はサイトエディターとグローバルスタイルが中心になり、通常は「外観」メニューにカスタマイザーが表示されません(2026年10月現在)。プラグインなどが customize_register を使っている場合は表示されることがありますが、ブロックテーマで新しく設定項目を作るなら、theme.json やブロックのスタイル設定で表現できないかを先に検討するほうが、エディターとの整合が取れます。カスタマイザー API が本領を発揮するのは、ヘッダーやフッターを PHP テンプレートで組んでいるクラシックテーマです。
まとめ
- カスタマイザーはセクション・セッティング・コントロールの3つで構成され、値を保存するのはセッティング。
- セッティングごとに
sanitize_callbackを指定し、選択肢は登録済みの値と照合する。出力時もesc_html()などでエスケープする。 get_theme_mod()にはadd_setting()と同じ初期値を渡す。- プレビューの即時反映は、PHP の出力を使うなら部分更新、CSS の変更だけなら JavaScript。子テーマでは
get_stylesheet_directory_uri()を使う。 theme_modはテーマごとに保存される。ブロックテーマではtheme.jsonやサイトエディターでの実現を先に検討する。