WordPress のサイドバーやフッターに、ドラッグ&ドロップでウィジェットを並べられる領域を作りたいことはよくあります。この「ウィジェットを置ける領域」のことをウィジェットエリア(サイドバー)と呼び、テーマ側で register_sidebar() を使って登録します。この記事では、register_sidebar() でウィジェットエリアを登録し、dynamic_sidebar() でテンプレートに表示するまでの一連の流れを、引数の意味や複数エリアの登録方法、表示されないときの対処までまとめて初心者向けに解説します。
目次
ウィジェットエリアとは何か
ウィジェットエリアは、管理画面の「外観 > ウィジェット」でブロックやウィジェットを自由に配置できる領域のことです。サイト運営者はコードを触らずに、検索フォームや最近の投稿、カテゴリー一覧といったパーツをドラッグ&ドロップで並べ替えられます。よくあるサイドバーやフッターのウィジェット枠が、このウィジェットエリアにあたります。
テーマ開発者がやることは大きく2つです。1つは register_sidebar() でウィジェットエリアを「登録」し、管理画面に枠を出すこと。もう1つは dynamic_sidebar() で、登録した枠に置かれたウィジェットをテンプレート上に「表示」することです。登録だけしても表示コードを書かなければ画面には出ませんし、逆に表示コードだけ書いても登録していなければ何も出ません。この2つはセットで考えます。
register_sidebar でウィジェットエリアを登録する
ウィジェットエリアの登録は、functions.php で register_sidebar() を呼び出して行います。重要なのは、この関数を widgets_init というフックの中で呼ぶことです。WordPress はウィジェット機能を初期化するタイミングでこのフックを実行するので、ここで登録するのが正しい作法です。フックの外でいきなり呼んでしまうと、登録が反映されず管理画面に枠が出ません。
function mytheme_widgets_init() {
register_sidebar( array(
'name' => __( 'メインサイドバー', 'mytheme' ),
'id' => 'sidebar-1',
'description' => __( '記事一覧の横に表示されるサイドバーです。', 'mytheme' ),
'before_widget' => '<section id="%1$s" class="widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h2 class="widget-title">',
'after_title' => '</h2>',
) );
}
add_action( 'widgets_init', 'mytheme_widgets_init' );
これで管理画面の「外観 > ウィジェット」に「メインサイドバー」という枠が表示され、ウィジェットを配置できるようになります。id に指定した sidebar-1 は、後でテンプレートからこのエリアを呼び出すときの識別子になります。
register_sidebar に渡す引数
register_sidebar() には連想配列で各種の設定を渡します。最低限 id を指定しておけば動きますが、見た目を整えるうえで before_widget などのマークアップ指定も重要です。主な引数は次のとおりです。
| 引数 | 説明 |
|---|---|
name | 管理画面に表示されるエリア名。指定しないと「Sidebar 1」のような連番名になる |
id | エリアを識別する ID。テンプレートからこの値で呼び出す。必須扱いで、小文字での指定が推奨される |
description | 管理画面に表示される説明文。何のためのエリアか運営者に伝えられる |
before_widget | 各ウィジェットの直前に出力される HTML。%1$s が ID、%2$s がクラス名に置き換わる |
after_widget | 各ウィジェットの直後に出力される HTML。before_widget で開いたタグを閉じる |
before_title | ウィジェットのタイトルの直前に出力される HTML。見出しタグの開始など |
after_title | ウィジェットのタイトルの直後に出力される HTML。見出しタグの終了など |
id は実質必須だと考えてください。省略すると WordPress が自動で連番の ID を割り当てますが、その値は予測しづらく、テンプレートから安定して呼び出せません。sidebar-1 のように、自分で分かりやすい小文字の ID を付けておくのが安全です。
before_widget / before_title でマークアップを整える
before_widget と after_widget は、エリア内に並ぶ各ウィジェットを囲むタグを決めます。先ほどの例では <section> で囲み、CSS で装飾しやすいようにクラスを付けています。%1$s と %2$s はプレースホルダで、WordPress が出力時にそれぞれウィジェットの ID とクラス名へ置き換えます。sprintf() と同じ書式なので、この記法のまま指定します。
before_title と after_title は、ウィジェットのタイトル(見出し)を囲むタグです。サイト全体で見出しレベルやクラスをそろえたいときに、ここで <h2> や <h3> を指定しておくと、どのウィジェットでも統一された見た目になります。これらを適切に設定しておくことで、運営者がどんなウィジェットを置いてもデザインが崩れにくくなります。
複数のウィジェットエリアを登録する
サイドバーとフッターの両方にウィジェットエリアを用意したい、というように複数のエリアが必要なことはよくあります。その場合は、register_sidebar() を必要な数だけ呼び出します。それぞれに別の id を割り当てるのがポイントです。
function mytheme_widgets_init() {
// メインのサイドバー
register_sidebar( array(
'name' => __( 'メインサイドバー', 'mytheme' ),
'id' => 'sidebar-1',
'before_widget' => '<section id="%1$s" class="widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h2 class="widget-title">',
'after_title' => '</h2>',
) );
// フッター用のウィジェットエリア
register_sidebar( array(
'name' => __( 'フッター', 'mytheme' ),
'id' => 'footer-1',
'before_widget' => '<section id="%1$s" class="widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h2 class="widget-title">',
'after_title' => '</h2>',
) );
}
add_action( 'widgets_init', 'mytheme_widgets_init' );
同じ設定を繰り返すのが冗長に感じる場合は、register_sidebars()(末尾が複数形)を使う方法もあります。第1引数に作りたい数、第2引数に共通の設定を渡すと、id が sidebar-1、sidebar-2 …と自動で連番になります。ただし個別に名前や説明を付けたいケースの方が多いため、実務では register_sidebar() を必要な回数だけ呼ぶ書き方がよく使われます。
dynamic_sidebar でテンプレートに表示する
登録したウィジェットエリアを実際のページに出力するには、テンプレートで dynamic_sidebar() を呼びます。引数には登録時に決めた id を渡します。サイドバーを担当する sidebar.php に書くのが一般的です。
このとき、いきなり dynamic_sidebar() を呼ぶのではなく、is_active_sidebar() で「そのエリアにウィジェットが1つ以上置かれているか」を確認してから出力するのが定石です。ウィジェットが何も置かれていないエリアを囲むタグだけ出力すると、空の枠が残って余白の原因になるためです。
<?php
// ウィジェットが1つでも配置されているときだけ出力する
if ( is_active_sidebar( 'sidebar-1' ) ) :
?>
<aside id="secondary" class="widget-area">
<?php dynamic_sidebar( 'sidebar-1' ); ?>
</aside>
<?php endif; ?>
あとは single.php や page.php など、サイドバーを表示したいテンプレートで get_sidebar() を呼べば、この sidebar.php が読み込まれます。get_sidebar( 'footer' ) のように引数を渡すと sidebar-footer.php が読み込まれるので、エリアごとにファイルを分けることもできます。
<?php get_header(); ?>
<main id="primary" class="site-main">
<?php
while ( have_posts() ) :
the_post();
the_content();
endwhile;
?>
</main>
<?php
// sidebar.php を読み込む
get_sidebar();
get_footer();
?>
これで「外観 > ウィジェット」でメインサイドバーに置いたウィジェットが、記事ページのサイドバーに表示されるようになります。登録した before_widget などの設定どおりに、各ウィジェットが <section> で囲まれ、タイトルが <h2> で出力されているはずです。
ウィジェットエリアが表示されないときに確認すること
「管理画面に枠が出ない」「テンプレートに何も表示されない」というつまずきは、register_sidebar まわりでよく起こります。原因は限られているので、順番に確認していきましょう。
widgets_init フックで登録していない
管理画面の「外観 > ウィジェット」にそもそも枠が出てこない場合、register_sidebar() を widgets_init フックの中で呼べていないことがよくあります。functions.php の先頭でいきなり register_sidebar() を実行しても、ウィジェット機能の初期化前なので正しく登録されません。必ず関数の中で呼び、add_action( 'widgets_init', ... ) でそのフックに登録してください。
登録した id とテンプレートの id が一致していない
管理画面には枠が出てウィジェットも配置できるのに、ページ側に何も表示されない場合は、register_sidebar() で指定した id と、dynamic_sidebar() や is_active_sidebar() に渡している文字列が食い違っている可能性が高いです。たとえば登録は sidebar-1 なのに、テンプレートでは sidebar1 や Sidebar-1 と書いていると一致しません。id は完全一致が必要で、大文字小文字も区別されます。両方の値を見比べて、まったく同じ文字列になっているか確認してください。
エリアにウィジェットを1つも置いていない
コードは正しいのに表示されない、というときに見落としがちなのが、エリアにウィジェットを1つも配置していないケースです。先ほどの sidebar.php では is_active_sidebar() で囲んでいるため、ウィジェットが空のときは <aside> ごと出力されず、画面には何も出ません。これはバグではなく意図した動作です。実際に表示を確認したいときは、「外観 > ウィジェット」で対象のエリアに検索フォームなどを1つ置いてから、ページを再読み込みしてみてください。
テンプレートで sidebar.php を読み込んでいない
sidebar.php に表示コードを書いていても、表示したいテンプレート(single.php や page.php など)で get_sidebar() を呼んでいなければ、そのファイルは読み込まれません。サイドバーが出ないページがあるときは、そのページを担当するテンプレートに get_sidebar() の呼び出しが書かれているかを確認しましょう。フッター用に別ファイルを使う場合は get_sidebar( 'footer' ) のように引数を合わせる必要もあります。
まとめ
ウィジェットエリアの作成は「登録」と「表示」の2ステップで覚えると整理しやすくなります。最後に要点を振り返っておきましょう。
register_sidebar()をwidgets_initフックの中で呼んで、ウィジェットエリアを登録する。- 引数では
idを必ず指定し、小文字で分かりやすい値にする。before_widgetなどでマークアップも整える。 - 複数エリアが必要なら
register_sidebar()を別々のidで必要なだけ呼ぶ。 - テンプレートでは
is_active_sidebar()で確認してからdynamic_sidebar()で表示し、テンプレート側からはget_sidebar()で読み込む。 - 表示されないときは、フック・
idの一致・ウィジェットの配置・get_sidebar()の呼び出しを順に確認する。
この流れを一度作ってしまえば、サイドバーやフッターなど好きな場所に、運営者が自由にカスタマイズできるウィジェット枠を用意できます。まずは sidebar-1 を1つ登録して表示するところから試してみてください。