このページはクラシック形式の自作テーマ向けです。
ブロックテーマのサイトエディターやSWELLの親テーマへそのまま貼る手順ではありません。
作業前にテーマファイルをバックアップし、本文の部分コードと末尾のまとめを重複して貼らないでください。
WordPressの自作テーマをスターターテーマを使わずにフルスクラッチで作成してみています。
ということで、今回はメニューとウィジェットを表示させてみます。
スターターテーマを使わずに
WordPress自作テーマを制作する
WordPressのメニューを表示する
外観のメニューからグローバルメニュー・フッターメニューを作成して表示させてみます。
管理画面にメニューを表示する
下記はテーマのメニュー対応を宣言するコードです。
後述のregister_nav_menu()でもメニュー対応が登録されるため、すでにメニュー位置を登録している場合に追加必須の処理ではありません。

// 外観のメニュー表示
add_theme_support('menus');メニュー設定
以下のコードをfunctions.phpに入れると、メニュー設定の項目にメニュー位置のオプションが設定できます。
function setup_nav_menu() {
register_nav_menu('global_menu', 'グローバルメニュー');
register_nav_menu('footer_menu', 'フッターメニュー');
}
add_action('after_setup_theme', 'setup_nav_menu');
メニューの表示
header.phpのメニューを表示させたい場所に、下記のコードを挿入します。
<nav class=" global-menu-nav">
<ul class="global-menu-list">
<?php
wp_nav_menu([
'container' => '',
'theme_location' => 'global_menu',
'fallback_cb' => false,
'items_wrap' => '%3$s',
'link_before' => '<span >',
'link_after' => '</span>',
]);
?>
</ul>
</nav>またfooter.phpのメニューを表示させたい場所に、下記のコードを挿入します。
<ul class="footer-menu-list">
<?php
wp_nav_menu([
'container' => '',
'theme_location' => 'footer_menu',
'fallback_cb' => false,
'items_wrap' => '%3$s',
'link_before' => '<span >',
'link_after' => '</span>',
]);
?>
</ul>| 項目 | 備考 |
|---|---|
| container | ulを囲う要素を指定(div, nav, false)※空白はfalseと同じ。 |
| theme_location | 登録した位置設定(ロケーション名)を指定 |
メニューの表示確認
以上の設定をしたうえで、状態の確認をしてみます。
ちゃんとメニューの表示が反映されました。
※グローバルメニューとフッターメニューにそれぞれカスタムリンクを3つ入れた状態です。

メニューの標準クラスを残す
メニューのクラスは現在位置や子メニューの有無を示します。
テーマのCSSや操作に使われるので、この例では削除しません。
<li id="menu-item-8" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home menu-item-8">下記は標準クラスとIDを残す方針を示したコメントです。
このコメントを追加しても、既存のクラス削除フィルターを解除する効果はありません。
旧コードを使っている場合は、そのフィルターの登録を確認して取り除いてください。
// メニューの標準クラス・IDは維持します。独自CSSでも current-menu-item や menu-item-has-children を利用できます。
クラス削除用の旧フィルターは追加しないでください。
<li class="menu-item current-menu-item">WordPressのウィジェットを表示する
次にウィジェットを設置してみます。
管理画面にウィジェットを表示する
下記はウィジェット対応を宣言するコードです。
後述のregister_sidebar()でもウィジェット対応は有効になるため、表示するエリアの登録まで進めてください。

// 外観のウィジェット表示
add_theme_support('widgets');ウィジェットエリアの登録
以下のコードをfunctions.phpに入れると、ウィジェットの項目に登録ができます。
function register_area() {
register_sidebar([
'name' => 'サイドバー',
'id' => 'sidebar',
'description' => 'サイドバーに表示されます。',
'before_widget' => '<div id="%1$s" class="%2$s">',
'after_widget' => '</div>',
]);
register_sidebar([
'name' => 'フッター',
'id' => 'footer',
'description' => 'フッターに表示されます。',
'before_widget' => '<div id="%1$s" class="%2$s">',
'after_widget' => '</div>',
]);
}
add_action('widgets_init', 'register_area');参考

+ボタンを押して、適当にテキストのブロックを追記しました。
ウィジェットの表示
サイドバー用のコードはsidebar.phpに、フッター用のコードはfooter.phpの表示したい場所に配置します。
完成版のfooter.phpはget_sidebar()でsidebar.phpを読み込むため、サイドバー用のコードをfooter.phpにも重ねて置かないでください。
サイドバー
<?php if (is_active_sidebar('sidebar')) : ?>
<div id="sidebar_widget">
<?php dynamic_sidebar('sidebar'); ?>
</div>
<?php endif; ?>フッター
<?php if (is_active_sidebar('footer')) : ?>
<div id="footer_widget">
<?php dynamic_sidebar('footer'); ?>
</div>
<?php endif; ?>ウィジェットの確認
ウィジェットエリアに入れたテキストブロックが表示されています。

この時点でのコードまとめ
- index.php → 前回から変更なし
- sidebar.php → 下記「サイドバーを一度だけ表示する完成版」の説明に従い、上のサイドバー用コードを配置
header.php
<!doctype html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="utf-8">
<meta name="format-detection" content="telephone=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php wp_body_open(); ?>
<nav class=" global-menu-nav">
<ul class="global-menu-list">
<?php
wp_nav_menu([
'container' => '',
'theme_location' => 'global_menu',
'fallback_cb' => false,
'items_wrap' => '%3$s',
'link_before' => '<span >',
'link_after' => '</span>',
]);
?>
</ul>
</nav>footer.php
<?php get_sidebar(); ?>
<!-- サイドバーはget_sidebar()で一度だけ読み込みます。 -->
<ul class="footer-menu-list">
<?php
wp_nav_menu([
'container' => '',
'theme_location' => 'footer_menu',
'fallback_cb' => false,
'items_wrap' => '%3$s',
'link_before' => '<span >',
'link_after' => '</span>',
]);
?>
</ul>
<footer id="footer">
<?php if (is_active_sidebar('footer')) : ?>
<div id="footer_widget">
<?php dynamic_sidebar('footer'); ?>
</div>
<?php endif; ?>
</footer>
<?php wp_footer(); ?>
</body>
</html>functions.php
<?php
// 外観のメニュー表示
add_theme_support('menus');
// 外観のウィジェット表示
add_theme_support('widgets');
// タイトルタグの表示
add_theme_support('title-tag');
// アイキャッチの表示
add_theme_support('post-thumbnails');
// WordPressのバージョン情報
remove_action('wp_head', 'wp_generator');
// 絵文字
add_filter('emoji_svg_url', '__return_false');
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('admin_print_scripts', 'print_emoji_detection_script');
remove_action('wp_print_styles', 'print_emoji_styles');
remove_action('admin_print_styles', 'print_emoji_styles');
// Windows Live Writeの停止
remove_action('wp_head', 'wlwmanifest_link');
// EditURI(RSD Link)の停止
remove_action('wp_head', 'rsd_link');
// 記号の自動変換停止(wptexturize無効化)
add_filter('run_wptexturize', '__return_false');
// https://api.w.org/の停止
remove_action('wp_head', 'rest_output_link_wp_head');
// ブロックとテーマの標準CSSは停止しません。
// メニューの標準クラス・IDは維持します。
// メニュー位置の設定
function setup_nav_menu() {
register_nav_menu('global_menu', 'グローバルメニュー');
register_nav_menu('footer_menu', 'フッターメニュー');
}
add_action('after_setup_theme', 'setup_nav_menu');
// ウィジェットエリアの登録
function register_area() {
register_sidebar([
'name' => 'サイドバー',
'id' => 'sidebar',
'description' => 'サイドバーに表示されます。',
'before_widget' => '<div id="%1$s" class="%2$s">',
'after_widget' => '</div>',
]);
register_sidebar([
'name' => 'フッター',
'id' => 'footer',
'description' => 'フッターに表示されます。',
'before_widget' => '<div id="%1$s" class="%2$s">',
'after_widget' => '</div>',
]);
}
add_action('widgets_init', 'register_area');
サイドバーを一度だけ表示する完成版
完成版のfooter.phpには、get_sidebar()でsidebar.phpを読む処理と、同じsidebarを直接出力する処理が重なっていました。
実テーマでウィジェットが2回表示され、sidebar_widgetのIDも重複することを再現したため、footer.phpの直接出力を外しました。
下の画面ではサイドバーの検証リンクが1回だけ表示されます。
sidebar.phpにウィジェットを出す処理を置き、footer.phpはget_sidebar()で読み込む構成に統一してください。
本文の部分コードと完成版を重複して追記しないことも必要です。
2026年10月2日の検証環境で、PC幅1280pxとスマホ幅390pxの親子メニュー・本文・ウィジェットを確認しました。
子リンクをEnterで開くと、リンク先の記事本文へ移動します。
この段階の例はメニュー階層を通常のリストで表示しており、折りたたみ式のスマホメニューは実装していません。
掲載コードはクラシックテーマ用です。
外観のウィジェットで保存した内容と公開側を比べ、テーマのCSSで整える前にもリンクと本文が読めるか確認してください。
戻す場合は変更前のfooter.phpを復元します。
全デザインの完成やブロックテーマへの対応を確認した結果ではありません。

ウィジェットを保存して公開表示を確かめる
ウィジェットエリアの登録ができたら、「外観 → ウィジェット」でサイドバーを開き、段落ブロックへ確認用の文字を入力します。
更新して画面を開き直し、文字が残っていることを確認してください。
ウィジェットの保存とPHPファイルの保存は別の操作です。
本記事のfunctions.php・sidebar.php・footer.phpを組み合わせた検証テーマで、段落「サイドバー保存確認20261002」を追加し、更新後の再読み込みと公開表示を確認しました。
PC幅1280pxとスマホ幅390pxで、確認用の段落とsidebarのIDはいずれも1回だけ表示されています。
画像には検証環境に既存のウィジェットも写っています。
同じ文字が2回出る場合は、完成版のfooter.phpにget_sidebar()とdynamic_sidebar()を重ねて書いていないか確認します。
管理画面では保存できても公開側に出ない場合は、登録したIDとsidebar.phpの呼び出し先を照合してください。
確認後は追加した段落を外し、必要なら変更前のウィジェット設定とファイルへ戻します。

メニューを保存して表示場所とリンク先を確認する
「外観 → メニュー」で作成したメニューを選び、投稿または固定ページの項目を追加します。
同じメニューを両方に表示する場合は、「グローバルメニュー」と「フッターメニュー」の両方を選択して保存します。
別の内容にする場合はメニューを分けて作成し、それぞれ対応する表示場所だけを選択して保存します。
編集画面を再読み込みして、項目名と選択した表示場所が保持されていることを確かめます。
テンプレートのwp_nav_menu()のtheme_locationを、functions.phpで登録したglobal_menuとfooter_menuに合わせてください。
表示場所の選択だけでは、テンプレートにメニューは追加されません。
公開側では長い項目名の折り返し、現在のページに付くcurrent-menu-item、Tabキーでの移動とEnterキーでのリンク先を確認します。
検証では1280pxと390pxの両方で保存した項目名が表示され、Enterキーで投稿へ移動できました。
元に戻すときは表示場所の選択を解除して保存し、テンプレートの変更もバックアップから戻します。

まとめ
今まで気になっていたメニューとウィジェット。
どちらともに似たような設定から表示することができました。
応用すれば好きな場所に表示ができるということで、既存のテーマでも応用できると思います。
過去のコードは、GitHubのMOTOKI-LLC/WAZA-codeにもまとめていますが、本文と異なる場合は本文の構成を参照してください。
メニュー未割当時は fallback_cb を false にして自動ページ一覧を出さない設定です。
「外観 → メニュー」で各位置に割り当てます。
変更後はTabで各リンクに移動できること、現在位置の表示、スマホで長いメニュー名が収まることを確認してください。
2023年の画面は当時の記録です。
後半の2026年10月2日の実画面は、記載した検証環境で確認した結果です。
戻すときは変更前のテーマファイルへ復元します。
公式仕様:wp_nav_menu。
GitHubの過去コードと本文が異なる場合は、今回修正した本文を参照してください。
完成版のfunctions.phpでは、ブロックライブラリ・クラシックテーマ・グローバルスタイルのCSSを一括停止しません。
投稿本文やウィジェット内のブロック表示に必要なためです。
既に旧版を貼った場合は、global-styles-inline-css、classic-theme-styles、wp-block-libraryの停止処理を削除してください。
この変更はメニュー登録やウィジェット登録には影響しません。



