2026年5月20日

2026年5月20日

WordPressのカスタマイザーAPIでリアルタイムプレビューを実装する方法

はじめに

WordPressのカスタマイザー(外観→カスタマイズ)は customize_register フックと WP_Customize_Manager を使って拡張できます。postMessage 転送を使うと、設定変更がリアルタイムでプレビューに反映される快適な編集体験を提供できます。

症状・原因

  • カスタマイザーにオリジナルの設定項目を追加したい
  • 設定を変更するとリアルタイムでプレビューに反映させたい
  • カラーピッカー・画像アップロード・テキストなどの入力コントロールを使いたい
  • カスタマイザーのセクションを整理してグループ化したい

解決手順

ステップ1:カスタマイザーにパネルとセクションを追加する

// functions.php
function mytheme_customize_register(WP_Customize_Manager $wp_customize): void {

    // パネルを追加(複数セクションをまとめる)
    $wp_customize->add_panel('mytheme_panel', [
        'title'       => 'テーマ設定',
        'description' => 'テーマの外観設定',
        'priority'    => 130,
    ]);

    // セクションを追加
    $wp_customize->add_section('mytheme_colors', [
        'title'    => 'カラー設定',
        'panel'    => 'mytheme_panel',
        'priority' => 10,
    ]);

    $wp_customize->add_section('mytheme_footer', [
        'title'    => 'フッター設定',
        'panel'    => 'mytheme_panel',
        'priority' => 20,
    ]);
}
add_action('customize_register', 'mytheme_customize_register');

ステップ2:設定とコントロールを追加する

// functions.php(customize_registerコールバック内に追記)
function mytheme_customize_register(WP_Customize_Manager $wp_customize): void {

    // === カラーピッカー ===
    $wp_customize->add_setting('mytheme_primary_color', [
        'default'           => '#2271b1',
        'sanitize_callback' => 'sanitize_hex_color',
        'transport'         => 'postMessage', // リアルタイム転送
    ]);

    $wp_customize->add_control(new WP_Customize_Color_Control(
        $wp_customize,
        'mytheme_primary_color',
        [
            'label'   => 'メインカラー',
            'section' => 'mytheme_colors',
        ]
    ));

    // === テキスト入力 ===
    $wp_customize->add_setting('mytheme_footer_text', [
        'default'           => '© ' . date('Y') . ' My Site',
        'sanitize_callback' => 'sanitize_text_field',
        'transport'         => 'postMessage',
    ]);

    $wp_customize->add_control('mytheme_footer_text', [
        'label'       => 'フッターテキスト',
        'section'     => 'mytheme_footer',
        'type'        => 'text',
        'input_attrs' => ['placeholder' => 'コピーライト文を入力'],
    ]);

    // === 画像アップロード ===
    $wp_customize->add_setting('mytheme_logo', [
        'default'           => '',
        'sanitize_callback' => 'absint', // 添付ファイルIDを整数でサニタイズ
        'transport'         => 'refresh',
    ]);

    $wp_customize->add_control(new WP_Customize_Media_Control(
        $wp_customize,
        'mytheme_logo',
        [
            'label'     => 'ロゴ画像',
            'section'   => 'mytheme_colors',
            'mime_type' => 'image',
        ]
    ));

    // === セレクトボックス ===
    $wp_customize->add_setting('mytheme_layout', [
        'default'           => 'sidebar-right',
        'sanitize_callback' => 'mytheme_sanitize_select',
    ]);

    $wp_customize->add_control('mytheme_layout', [
        'label'   => 'レイアウト',
        'section' => 'mytheme_footer',
        'type'    => 'select',
        'choices' => [
            'sidebar-right' => '右サイドバー',
            'sidebar-left'  => '左サイドバー',
            'no-sidebar'    => 'サイドバーなし',
        ],
    ]);
}
add_action('customize_register', 'mytheme_customize_register');

function mytheme_sanitize_select(string $value, WP_Customize_Setting $setting): string {
    $choices = $setting->manager->get_control($setting->id)->choices;
    return array_key_exists($value, $choices) ? $value : $setting->default;
}

ステップ3:postMessageでリアルタイムプレビューを実装する

// js/customizer.js: カスタマイザーのJSプレビュー制御
(function ($) {
    'use strict';

    // メインカラーをリアルタイムで反映
    wp.customize('mytheme_primary_color', function (value) {
        value.bind(function (newColor) {
            // CSS変数を更新
            document.documentElement.style.setProperty('--color-primary', newColor);

            // 直接スタイルを変更する場合
            $('.site-header').css('background-color', newColor);
        });
    });

    // フッターテキストをリアルタイムで反映
    wp.customize('mytheme_footer_text', function (value) {
        value.bind(function (newText) {
            $('.site-footer .footer-text').text(newText);
        });
    });

}(jQuery));
// functions.php: カスタマイザーJSをエンキュー
function mytheme_customize_preview_js(): void {
    wp_enqueue_script(
        'mytheme-customizer',
        get_template_directory_uri() . '/js/customizer.js',
        ['customize-preview', 'jquery'],
        wp_get_theme()->get('Version'),
        true
    );
}
add_action('customize_preview_init', 'mytheme_customize_preview_js');

ステップ4:設定値をテンプレートで出力する

// functions.php
function mytheme_customize_css(): void {
    $primary_color = get_theme_mod('mytheme_primary_color', '#2271b1');
    ?>
    <style id="mytheme-customizer-css">
        :root {
            --color-primary: <?php echo esc_attr($primary_color); ?>;
        }
        .site-header { background-color: <?php echo esc_attr($primary_color); ?>; }
    </style>
    <?php
}
add_action('wp_head', 'mytheme_customize_css');

// テンプレート内でのテキスト取得
$footer_text = get_theme_mod('mytheme_footer_text', '© ' . date('Y') . ' My Site');
echo wp_kses_post($footer_text);

注意事項

  • transport => 'postMessage' を指定した設定は、必ずJavaScriptでプレビュー更新を実装してください。JSがないと変更が反映されません
  • transport => 'refresh' はページ全体をリロードしてプレビューを更新します。画像やレイアウト変更など、JSでは難しい変更に使います
  • get_theme_mod() はカスタマイザーの設定値を取得します。get_option() とは異なり、デフォルト値を第2引数で指定できます

まとめ

customize_register フックで add_paneladd_sectionadd_settingadd_control を組み合わせてカスタマイザーを拡張します。transport: postMessage + customize_preview_init のJSで即時反映を実現し、テンプレートでは get_theme_mod() で値を取得して wp_head でCSSに出力します。

お気軽にご相談ください

お見積りへ お問い合わせへ