2026年10月31日

2026年10月31日

WordPressテーマカスタマイザーに独自設定を追加する方法

はじめに

WordPressのテーマカスタマイザー(外観 → カスタマイズ)に独自の設定項目を追加することで、コードを書かずにサイトのデザインを変更できるUI を提供できます。この記事では、セクション・設定・コントロールの追加からライブプレビューの実装まで解説します。

症状・原因

  • テーマカスタマイザーに独自の色設定やテキスト入力フィールドを追加したいが方法がわからない
  • カスタマイザーの設定値を get_theme_mod() でテンプレートに出力する方法がわからない
  • ライブプレビュー(設定変更をリアルタイムで確認)が実装できていない
  • セレクティブリフレッシュを使ってパフォーマンスを改善したい

解決手順

ステップ1:customize_register フックでセクション・設定・コントロールを追加する

customize_register フックで WP_Customize_Manager オブジェクトを受け取り、独自の設定を追加します。

function mytheme_customize_register( WP_Customize_Manager $wp_customize ) {

    // ===== セクションの追加 =====
    $wp_customize->add_section('mytheme_header_section', [
        'title'       => 'ヘッダー設定',
        'description' => 'ヘッダーエリアの設定を変更できます。',
        'priority'    => 30,     // 数値が小さいほど上に表示
        'capability'  => 'edit_theme_options',
    ]);

    // ===== 設定の追加(色の設定) =====
    $wp_customize->add_setting('mytheme_header_bg_color', [
        'default'           => '#0073aa',
        'transport'         => 'postMessage',  // ライブプレビュー用
        'sanitize_callback' => 'sanitize_hex_color',
    ]);

    // ===== カラーピッカーコントロールの追加 =====
    $wp_customize->add_control(
        new WP_Customize_Color_Control(
            $wp_customize,
            'mytheme_header_bg_color',
            [
                'label'   => 'ヘッダー背景色',
                'section' => 'mytheme_header_section',
            ]
        )
    );

    // ===== テキスト入力の設定 =====
    $wp_customize->add_setting('mytheme_header_tagline', [
        'default'           => '',
        'transport'         => 'refresh',
        'sanitize_callback' => 'sanitize_text_field',
    ]);

    $wp_customize->add_control('mytheme_header_tagline', [
        'type'        => 'text',
        'label'       => 'キャッチコピー',
        'description' => 'ヘッダーに表示するキャッチコピーを入力してください。',
        'section'     => 'mytheme_header_section',
        'input_attrs' => [
            'placeholder' => 'あなたのキャッチコピーを入力',
            'maxlength'   => 50,
        ],
    ]);

    // ===== セレクトボックスの設定 =====
    $wp_customize->add_setting('mytheme_font_size', [
        'default'           => '16px',
        'transport'         => 'postMessage',
        'sanitize_callback' => 'mytheme_sanitize_select',
    ]);

    $wp_customize->add_control('mytheme_font_size', [
        'type'    => 'select',
        'label'   => 'フォントサイズ',
        'section' => 'mytheme_header_section',
        'choices' => [
            '14px' => '小(14px)',
            '16px' => '中(16px)',
            '18px' => '大(18px)',
        ],
    ]);
}
add_action('customize_register', 'mytheme_customize_register');

ステップ2:sanitize_callback でセキュリティを確保する

カスタマイザーの設定値は必ずサニタイズ関数を指定してください。悪意のあるデータが保存されないようにします。

// セレクトボックスのサニタイズ関数
function mytheme_sanitize_select( $value, $setting ) {
    // 許可された選択肢の一覧を取得
    $choices = $setting->manager->get_control($setting->id)->choices;

    // 許可された値なら返す、そうでなければデフォルト値を返す
    if ( array_key_exists($value, $choices) ) {
        return $value;
    }

    return $setting->default;
}

// チェックボックスのサニタイズ
function mytheme_sanitize_checkbox( $checked ) {
    return ( isset($checked) && $checked === true ) ? true : false;
}

// URLのサニタイズ
function mytheme_sanitize_url( $url ) {
    return esc_url_raw($url);
}

// HTML(リミテッド)のサニタイズ
function mytheme_sanitize_html( $html ) {
    return wp_kses_post($html);
}

// 数値のサニタイズ(範囲チェック付き)
function mytheme_sanitize_range( $value, $setting ) {
    $attr = $setting->manager->get_control($setting->id)->input_attrs;
    $min  = isset($attr['min']) ? $attr['min'] : $value;
    $max  = isset($attr['max']) ? $attr['max'] : $value;
    $step = isset($attr['step']) ? $attr['step'] : 1;

    $value = absint($value);
    return ( $min <= $value && $value <= $max )
        ? $value
        : $setting->default;
}

ステップ3:get_theme_mod() でテンプレートに値を出力する

カスタマイザーで保存した設定値は get_theme_mod() で取得してテンプレートやCSSに出力します。

// header.php での使用例
function mytheme_output_customizer_css() {
    // 設定値の取得(第2引数はデフォルト値)
    $header_bg   = get_theme_mod('mytheme_header_bg_color', '#0073aa');
    $font_size   = get_theme_mod('mytheme_font_size', '16px');
    $tagline     = get_theme_mod('mytheme_header_tagline', '');

    // CSS変数として出力
    $css = "
    :root {
        --header-bg-color: " . sanitize_hex_color($header_bg) . ";
        --body-font-size:  " . esc_attr($font_size) . ";
    }
    .site-header {
        background-color: var(--header-bg-color);
    }
    body {
        font-size: var(--body-font-size);
    }
    ";

    // インラインスタイルとして追加
    wp_add_inline_style('child-style', $css);
}
add_action('wp_enqueue_scripts', 'mytheme_output_customizer_css');

// テンプレートファイルでの使用例(header.php)
function mytheme_display_tagline() {
    $tagline = get_theme_mod('mytheme_header_tagline', '');
    if ( ! empty($tagline) ) {
        echo '<p class="site-tagline">' . esc_html($tagline) . '</p>';
    }
}

ステップ4:postMessage transport でライブプレビューを実装する

transport => 'postMessage' を設定した項目は、JavaScriptでリアルタイムプレビューを実装する必要があります。

// wp-content/themes/mytheme-child/js/customizer-preview.js

( function( $ ) {
    'use strict';

    // ヘッダー背景色のライブプレビュー
    wp.customize( 'mytheme_header_bg_color', function( value ) {
        value.bind( function( newValue ) {
            // CSS変数を更新してリアルタイムで反映
            document.documentElement.style.setProperty(
                '--header-bg-color',
                newValue
            );
            // または直接スタイルを変更
            $( '.site-header' ).css( 'background-color', newValue );
        } );
    } );

    // フォントサイズのライブプレビュー
    wp.customize( 'mytheme_font_size', function( value ) {
        value.bind( function( newValue ) {
            document.documentElement.style.setProperty(
                '--body-font-size',
                newValue
            );
        } );
    } );

} )( jQuery );
// functions.php - プレビュースクリプトの読み込み
function mytheme_customize_preview_js() {
    wp_enqueue_script(
        'mytheme-customizer-preview',
        get_stylesheet_directory_uri() . '/js/customizer-preview.js',
        ['customize-preview', 'jquery'],
        wp_get_theme()->get('Version'),
        true
    );
}
add_action('customize_preview_init', 'mytheme_customize_preview_js');

ステップ5:セレクティブリフレッシュでパフォーマンスを最適化する

セレクティブリフレッシュは、設定が変更された時にページ全体を再読み込みするのではなく、対象の部分だけを更新します。

function mytheme_customize_register( WP_Customize_Manager $wp_customize ) {
    // セレクティブリフレッシュのサポートを確認
    $wp_customize->selective_refresh->add_partial('mytheme_header_tagline', [
        'selector'        => '.site-tagline',    // 更新するDOM要素のCSSセレクター
        'render_callback' => 'mytheme_display_tagline_partial',
        'container_inclusive' => false,           // セレクター自体を含めるか
        'fallback_refresh'    => true,            // DOMが見つからない場合は全体リフレッシュ
    ]);

    // ロゴ画像のセレクティブリフレッシュ
    $wp_customize->selective_refresh->add_partial('custom_logo', [
        'selector'        => '.custom-logo-link',
        'render_callback' => function() {
            return get_custom_logo();
        },
        'container_inclusive' => true,
    ]);
}

// セレクティブリフレッシュ用のレンダリングコールバック
function mytheme_display_tagline_partial() {
    $tagline = get_theme_mod('mytheme_header_tagline', '');
    if ( ! empty($tagline) ) {
        echo esc_html($tagline);
    }
}

// セレクティブリフレッシュのサポートをテーマで宣言
function mytheme_setup() {
    add_theme_support('customize-selective-refresh-widgets');
    add_theme_support('custom-logo', [
        'height'      => 100,
        'width'       => 300,
        'flex-width'  => true,
        'flex-height' => true,
    ]);
}
add_action('after_setup_theme', 'mytheme_setup');

注意事項

  • sanitize_callback は必ず指定してください。指定しない場合はデータがそのままデータベースに保存され、XSSやSQLインジェクションの原因になります。
  • transport => 'postMessage' を設定した場合、必ず対応するJavaScriptのプレビューコードも実装してください。実装しないとカスタマイザーで変更しても画面が更新されません。
  • セレクティブリフレッシュの render_callback が返す内容は、フロントエンドの実際の表示と一致させる必要があります。不一致の場合、プレビューと実際の表示が異なります。

まとめ

テーマカスタマイザーへの設定追加は、customize_register フックでのセクション・設定・コントロール定義、get_theme_mod() での値の取得・出力、postMessage トランスポートとJavaScriptによるライブプレビューの3ステップが核心です。セレクティブリフレッシュを導入することで、より快適なカスタマイズ体験を提供できます。関連記事:WordPressにブロックパターンを作成・登録してコンテンツ制作を効率化する方法

お気軽にご相談ください

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