MENU CLOSE

【WordPress】
テーマカスタマイザーを
作成する

WordPress Theme Customizer

テーマカスタマイザーとは

WordPressの管理画面でプレビューしながらコンテンツを編集・更新・公開できる機能です。 テキストなどを入力エリアに打ち込むとリアルタイムでプレビューが更新されるので直感的でわかりやすく、初心者でも簡単に修正・更新ができます。

具体的にはWordPressの管理画面に入って「外観 → カスタマイズ」で表示される画面のことです。 何も設定していないとうまく使えませんが、対応しているテーマの場合はここからコンテンツを変更できます。

WordPressの受託案件で何度か使うことがあり、自作することが多くなったので使った方法やコードを一度まとめてメモとして残しておきたいと思います。

公式では「テーマカスタマイズAPI」としてcodexに情報が掲載されています。

テーマカスタマイズAPI

https://wpdocs.osdn.jp/%E3%83%86%E3%83%BC%E3%83%9E%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA_API

テーマカスタマイザーの作成方法

今回は記事を書くに当たって、このブログのABOUTページにテーマカスタマイザーを追加しましたので、その手順をご紹介します。

ABOUTページ テーマカスタマイザー
ABOUTページ テーマカスタマイザー

設定する前に

テーマカスタマイザーはWordPressに元から入っているjQueryを使いますので、それをアクションフックで読み込まないようにしている場合は必ず読み込むように設定しておいてください。

アクションフック

functions.phpにアクションフックを追記します。

function my_theme_customize_register($wp_customize)
{
  //ここにカスタマイザーの作成処理を書く
}
add_action('customize_register', 'my_theme_customize_register');

customize_registerフックを使ってテーマカスタマイザーに設定を追加します。
テーマカスタマイザーの作成には、大きく分けて「セクション」「テーマ」「コントロール」の3つの設定を追加する必要があります。

セクションの追加

$wp_customize->add_section(
  'about_section',
  [
    'title'           => 'ABOUT',
    'priority'        => 1,
    'active_callback' => function () {
      //ABOUTページのみ表示
      return is_page('about');
    }
  ]
);

主なパラメーター設定項目は以下です。

  • title => カスタマイザーに表示するセクションの名前
  • priority => 表示順序(小さい方が優先度が高い)
  • active_callback => 条件によって表示・非表示を調整できる
  • description => 説明文

ここではABOUTページだけ表示させるようにしました。

テーマの追加

$wp_customize->add_setting(
  //任意で一意のIDを付ける
  'about_lead_title',
  [
    'default'     => 'このブログについて',
    'transport'   => 'postMessage'
  ]
);

主なパラメーター設定項目は以下です。

  • default => 初期値
  • transport => リアルタイムで入力情報を反映させる(postMessage)か、入力するたびにリロードする(refresh)かを指定できる。初期値はrefresh
  • type => 保存する値をoptiontheme_modかを指定できる。初期値はtheme_mod
  • capability => 権限設定
  • sanitize_callback => サニタイズする関数を追加できる。

ここではABOUTページの「このブログについて」の見出しをカスタマイズしたいので、defaultとリアルタイムプレビューのみを設定。
typeに関しては、optionsはデータベースにIDと紐づけて保存する、theme_modはテーマ名と紐づけて保存するといった違いみたいなので、子テーマ・親テーマとかで使い回す場合はoptions、それ以外はtheme_modでいいと思います。
capability、sanitize_callbackに関してはこのブログに関しては必要がないので割愛します。公式テーマを作る人は必ず設定した方がいいそうです。

コントロールの追加

$wp_customize->add_control(
  //コントロールID
  "control_about_lead_title",
  [
    // add_settingで設定したID
    'settings'    => 'about_lead_title',
    // カスタマイザー画面で表示するラベル名
    'label'       => 'リードコンテンツ:タイトル',
    // 表示するセクションを指定
    'section'     => 'about_section',
    // フォームの種類を指定
    'type'        => 'text'
  ]
);

主なパラメーター設定項目は以下です。

  • settings => add_settingで設定したIDを指定
  • label => カスタマイザー画面で表示するラベル名
  • section => 表示するセクションを設定したセクションIDで指定
  • type => フォームの種類を指定。

フォームで指定できる種類は下記。

  • text => テキスト
  • checkbox => チェックボックス
  • radio => ラジオボタン
  • select => セレクトボックス
  • textarea => テキストエリア
  • dropdown-pages => 固定ページのドロップダウン
  • email => メールアドレス
  • url => URL
  • number => 数値

ここでは先ほどの設定したテーマ・セクションに紐付けて、実際に入力するエリアを設定します。テキストを変更したいので、テキストボックスを表示させました。

カスタマイザー コントロール設定例
カスタマイザー コントロール設定例

セレクティブリフレッシュの設定

通常、カスタマイザーの項目に入力するとけっこうな頻度でプレビュー画面がリロードされてちょっと使いにくいのですが、selective_refreshを使うことでリロードさせずにAjaxで部分的に更新できます。

これを設定する場合の注意点として、先ほどのテーマ設定で

'transport' => 'postMessage'

としておく必要があります。

実際の追加設定は以下です。

$wp_customize->selective_refresh->add_partial(
  //部分的に更新したいコントロールのID
  'about_lead_title',
  [
    'selector'            => "#about_lead_title-customizer",
    'container_inclusive' => false,
    'render_callback'     => function ($partial = null) {
      return get_theme_mod($partial->id, 'このブログについて');
    }
  ]
);

主なパラメーター設定項目は以下です。

  • selector => 更新したいhtmlのセレクタ( jQuery )を指定します。
  • container_inclusive => 指定した要素ごと変更するか(true)、中身だけ変更するか(false)
  • render_callback => コールバックをレンダリングします。

ここでは部分的に更新したい要素にabout_lead_title-customizerというIDを付けてコントロールと連携させます。render_callbackではこの部分の情報を引数で取れるので、IDを取得し、カスタマイザーに保存した値を出力する関数get_theme_mod()で返します。

ウィジェットのセレクティブリフレッシュ

ウィジェットの入力も部分更新したいって場合は下記を追記。

function customizer_widgets()
{
  add_theme_support('customize-selective-refresh-widgets');
}
add_action('init', 'customizer_widgets');

テンプレートへの出力方法

テンプレートファイルでは以下のようにして出力します。

<h2 id="about_lead_title-customizer"><?php echo esc_html(get_theme_mod('about_lead_title', 'このブログについて'))?></h2>

先ほどもちらっと登場したget_theme_mod()関数を使って表示します。第一引数はコントロールのID、第2引数は初期値です。

selective_refreshを使ったライブプレビューを適用するためにh2要素にidabout_lead_title-customizerを指定します。

ちなみに、このidはテーマカスタマイザー上でしか必要ないのでは?と思って、is_customize_preview()関数を使い、プレビュー画面の時だけidを付けてみたのですがうまく動きませんでした。selective_refreshを多用する場合は少々htmlのコード量が多くなりますが仕方ないですね。

実際に書いたコード

ここまでの方法で追加できるのはできます。

ただ正直1つ1つ作ってたらめちゃめちゃコード量多くなるやん・・・!ってなりますので、僕はある程度ルールを決めてループを回して設定するようにしています。

function my_theme_customize_register($wp_customize)
{
  about_customizer($wp_customize);
}
add_action('customize_register', 'my_theme_customize_register');

/*
* ABOUT
* @param {Object$} wp_customize
*/
function about_customizer($wp_customize)
{
  $prefix = 'about';
  $option_name = "${prefix}_options";
  $section_name = "${prefix}_section";
  //セクション設定
  $wp_customize->add_section(
    $section_name,
    [
      'title'           => 'ABOUT',
      'priority'        => 1,
      'active_callback' => function () {
        return is_page('about');
      }
    ]
  );
  //セクション内の各フィールドオプション設定
  $fields = [
    'about_lead_title' => [
      'label'       => 'リードコンテンツ:タイトル',
      'type'        => 'text',
      'default'     => 'このブログについて'
    ],
    'about_lead_summary' => [
      'label'       => 'リードコンテンツ:概要',
      'type'        => 'textarea',
      'default'     => 'notes by sharesl(以下「当ブログ」)は、株式会社SHARESLが運営している開発者ブログです。<br>開発者が日々考えていることのアウトプットやメモとして残しておきたい備忘録としての記事を更新していきます。<br>最新技術やトレンドの記事というよりは、WEBサイト制作の実務の中で気づいたことをまとめて後で見返せるノートのような役割を目的としています。'
    ],
    'company_name' => [
      'label'       => '会社名',
      'type'        => 'text',
      'default'     => '株式会社SHARESL(シェアスル)'
    ],
    'company_url' => [
      'label'       => 'コーポレートサイトURL',
      'type'        => 'url',
      'default'     => 'https://sharesl.net/'
    ],
    'company_establishment_date' => [
      'label'       => '設立',
      'type'        => 'date',
      'default'     => '2015年5月1日'
    ],
    'company_ceo' => [
      'label'       => '代表取締役',
      'type'        => 'text',
      'default'     => '兼石 裕司'
    ],
    'company_business' => [
      'label'       => '事業内容',
      'type'        => 'textarea',
      'default'     => 'インターネットサービス<br>プリント・撮影関連事業<br>イベント運営'
    ],
    'company_place' => [
      'label'       => '所在地',
      'type'        => 'textarea',
      'default'     => '大阪市中央区心斎橋筋1-3-12'
    ],
    'company_email' => [
      'label'       => '連絡先',
      'type'        => 'email',
      'default'     => 'hello@sharesl.net'
    ],
    'about_terms_title' => [
      'label'       => '規約:タイトル',
      'type'        => 'text',
      'default'     => '免責事項'
    ],
    'about_terms_summary' => [
      'label'       => '規約:内容',
      'type'        => 'textarea',
      'default'     => '当ブログは正当で確実な情報をまとめたものではありませんので、掲載された情報で生じた問題については一切の責任を追いません。また、コメントやお問い合わせ等で個人的なカスタマイズのご質問は基本的にはご対応いたしません。カスタマイズを含めてお仕事としてご依頼される場合はお問い合わせから株式会社SHARESLを通してご連絡ください。また、本免責事項等及び、当ブログに掲載されている情報は予告なしに変更、または削除されることがあります。ご了承ください。'
    ],
    'about_remarks_title' => [
      'label'       => '備考:タイトル',
      'type'        => 'text',
      'default'     => '当サイトのアクセス解析ツールに関して'
    ],
    'about_remarks_summary' => [
      'label'       => '備考:概要',
      'type'        => 'textarea',
      'default'     => '<p>当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。<br>このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。<br>このトラフィックデータは匿名で収集されており、個人を特定するものではありません。</p><p>この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。この規約に関して、詳しくは「<a href="https://www.google.com/analytics/terms/jp.html" target="_blank" rel="noreferrer noopener">Google アナリティクス利用規約</a>」をご覧ください。</p>'
    ]
  ];
  //セクションにフォームコントロールを追加
  add_customizer_contol($wp_customize, $fields, $option_name, $section_name);
}

/*
* テーマカスタマイザーにフォームコントロールを追加する
* @param {Object} $wp_customize
* @param {Object} $fields 追加するオプションの配列
* @param {Object} $fields 追加するオプション名
* @param {Object} $section_name 追加するセクション名
*/
function add_customizer_contol($wp_customize, $fields, $option_name, $section_name)
{
  foreach ((array)$fields as $id => $value) {
    $default = !empty($value['default']) ? $value['default'] : null;
    $wp_customize->add_setting(
      $id,
      [
        'default'     => $default,
        'transport'   => 'postMessage'
      ]
    );
    $wp_customize->selective_refresh->add_partial(
      $id,
      [
        'selector'            => "#${id}-customizer",
        'container_inclusive' => false,
        'render_callback'     => function ($partial = null) {
          return get_theme_mod($partial->id, $default);
        }
      ]
    );
    $wp_customize->add_control(
      "${option_name}_${id}",
      [
        'settings'    => $id,
        'label'       => $value['label'],
        'section'     => $section_name,
        'type'        => !empty($value['type']) ? $value['type'] : 'textarea',
        'description' => !empty($value['description']) ? $value['description'] : null,
        'choices'     => !empty($value['choices']) ? $value['choices'] : null
      ]
    );
  }
}

こんな感じで10個以上のコントロールがありますが、配列でまとめて指定してあとはループで回すようにしています。これでも長いですが、1つずつ書くよりはかなりコードが短くて済むので良いかと。

最終的にはこんな感じ↓

カスタマイズプレビュー画面
カスタマイズプレビュー画面

今回のABOUTページでは画像がなかったので設定は省きましたが、画像もカスタマイザーに含ませることができるみたいです。また機会があれば追記します。

テーマカスタマイザーの使い所

こんなにコード量や設定項目が多いとテーマへ導入するハードルは高いと思います。 また、導入コストが高い割に実際にはあまり使われなかった・・・なんてこともありえますので、どんな時に導入すれば良いか、メリット・デメリットを挙げて考えてみました。

メリット

  • プレビューを見ながら直感的な操作で編集・更新が可能なので、初心者でも簡単に扱える
  • 画面ごとにコンテンツを集約することができるので、固定ページに行ったり、投稿ページに行ったりと管理画面を行ったり来たりせずに編集できる
  • 入力フィールドが多くなっても変更しやすい。
  • 保存した情報はカスタムフィールドと違い、データを記事IDで管理していないのでどこからでも呼び出すことが可能。

デメリット

  • コントロールやセクションを動的に増やしてループさせる、といったことはできない
  • ビジュアルエディターが使えないので長文の編集には向かない
  • フィールドが多くなればfunctions.phpに相当量のコードを書く必要がありコンテンツが多いサイトでは導入にかなりコストがかかる
  • 後から別の更新方法に変えるのは大変なので、一度使い始めるとロックインされそう

こんなところですかね。
僕の所感としては、10~15ページ以下の小規模コーポレートサイトや、簡単なLP、ポートフォリオサイトなど、固定ページのコンテンツ更新を頻繁に行うようなWebサイトには向いているかなーという感じです。

逆に合わないのは100ページ以上の中規模サイトや、会員サイト・ECサイトなどの動的なサイト、エディタを使って投稿することがメインのメディアサイトなど。
こういったあまりにも多すぎる固定ページを持ったサイトや、逆にほとんど固定ページを持たないサイトに導入しようとすると、コストがかかるだけなのでオススメできないです。 おそらくこういうサイトに機能として付けてもあまり触ることもないまま次のリニューアルを迎えることになると思います。

まとめると、

  • 固定ページにコンテンツが多い
  • 固定ページを頻繁に更新する
  • 固定ページが多すぎない

このようなサイトに限り有効な機能だと思います。

最近受けた案件では、コーポレートサイトで英語対応もしたいけど自動翻訳は使わず任意のテキストを入力したいっていう時に、テーマカスタマイザーを使いました。
カスタムフィールドだと、WordPressのプレビューが直前のリビジョンを使うという仕様上、プレビューが全く使えません。
プレビューが使えないと英語と日本語でテキストの長さが変わってしまってレイアウトが崩れる場合や、改行位置が変な箇所についてしまう場合があります。
テーマカスタマイザーを使うとリアルタイムでプレビューを確認できて便利です。
また、更新手順も少なくて済みました。
通常カスタムフィールドだけで作ったサイトだと、

管理画面の固定ページに入って、
該当のページを探して、
該当のカスタムフィールドを探して、
修正して、
更新して、
PCフロントのページを確認して、
スマホのページも確認して・・・

という流れになります。
一方、テーマカスタマイザーを使えば

管理画面のカスタマイザーに入って、
プレビューで該当のページに入って、
該当のエリアを編集しながらデバイスごとの見た目も確認して、
OKなら公開

というように更新作業を大幅に短縮できます!

おわりに

WordPressのテーマカスタマイザーを自分で作ってカスタマイズプレビュー画面でライブプレビューできるようにするところまでをまとめました。

導入までのハードルは少し高いかもしれませんが、理解して使いこなせるとWordPressの提案としてひとつ武器が増えるので、かなり強力です!WordPress案件を受けることが多いけどまだ試したことがないという方は一度試しておくことをおすすめします。
ここに書いてあるテキストコンテンツの更新の使い方だけでなく、バナー画像の変更やテーマカラーの変更などもカスタマイザーに取り込めるのでテーマの作り方によってはカスタマイザーのみですべての箇所を更新できるように作ることも可能です。

記事一覧

RELATED

WebP
inoue
inoue
TIPS

Gulpを使ってWebP画像を生成する方法【Gulp4】

howler.js
inoue
inoue
TIPS

howler.jsの使い方[音声ファイルの再生・停止]

object-fit
inoue
inoue
TIPS

【CSS】object-fitの使い方[IE11対応]

nuxt + netlify
inoue
inoue
TIPS

Nuxt.js + Netlifyで問い合わせフォームを作る方法【自動返信あり】

Dropdown Menu
inoue
inoue
TIPS

レスポンシブなドロップダウンメニューをつくる

imagesLoaded
inoue
inoue
TIPS

「imagesLoaded」を使って画像の読み込みを検知する

ブログ記事一覧
  • HOME
  • TIPS
  • 【WordPress】テーマカスタマイザーを作成する