「メニューの項目をお客さん自身で変えられるようにしてほしい」——この要件はregister_nav_menus()とwp_nav_menu()の2つで実現できます。手順は3ステップです。
手順1:メニューの場所をテーマに登録する
function my_register_menus() {
register_nav_menus([
'global' => 'ヘッダーメニュー',
'footer' => 'フッターメニュー',
]);
}
add_action('after_setup_theme', 'my_register_menus');キー(global)がテンプレートから呼ぶ名前、値が管理画面に出る表示名です。
手順2:テンプレートで呼び出す
<?php
wp_nav_menu([
'theme_location' => 'global',
'container' => false, // 囲みのdivを出さない
'items_wrap' => '<ul class="global-nav">%3$s</ul>',
'depth' => 2,
]);
?>手順3:管理画面でメニューを作る
- 「外観」→「メニュー」を開く
- 「新規メニューを作成」→名前を入れて「メニューを作成」
- 左から固定ページ・カテゴリ・カスタムリンクを追加してドラッグで並べ替え
- 「メニュー設定」の「メニューの位置」で「ヘッダーメニュー」にチェック
- 「メニューを保存」
引数の早見表
| 引数 | 役割 | 例 |
|---|---|---|
theme_location | どの場所のメニューか | 'global' |
container | 囲みの要素 | false(出さない)/ 'nav' |
container_class | 囲みのclass | 'nav-wrap' |
menu_class | ulに付くclass | 'global-nav' |
items_wrap | ul部分のマークアップ | '<ul class="x">%3$s</ul>' |
depth | 何階層まで出すか | 1(子を出さない)/ 2 |
fallback_cb | メニュー未設定時の代替 | false(何も出さない) |
walker | 出力を細かく制御 | new My_Walker() |
自動で付くclassを使う
WordPressは各liに状態を表すclassを付けてくれます。CSSを当てるだけで動きが作れます。
| class | 付くとき |
|---|---|
current-menu-item | 今表示しているページの項目 |
current-menu-parent / current-menu-ancestor | その親の項目 |
menu-item-has-children | 子メニューを持つ項目 |
menu-item-{ID} | 項目ごとの固有class |
.global-nav { display: flex; gap: 1.5rem; list-style: none; }
.global-nav a { text-decoration: none; padding: 0.5em 0; display: inline-block; }
.global-nav .current-menu-item > a { border-bottom: 2px solid currentColor; font-weight: 700; }ドロップダウン(子メニュー)
管理画面でドラッグして右にずらすと子項目になります。CSSだけでドロップダウンにできます。
.global-nav .menu-item-has-children { position: relative; }
.global-nav .sub-menu {
position: absolute;
top: 100%;
left: 0;
min-width: 12em;
list-style: none;
background: #fff;
box-shadow: 0 8px 24px rgb(0 0 0 / 0.12);
border-radius: 8px;
padding: 0.5rem 0;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s ease;
}
.global-nav .menu-item-has-children:hover .sub-menu,
.global-nav .menu-item-has-children:focus-within .sub-menu {
opacity: 1;
visibility: visible;
}:focus-withinも入れておくと、キーボード操作でも開くようになります。マウスだけを前提にしないのが親切な作りです。
スマホのハンバーガーメニュー
<button class="menu-toggle" aria-expanded="false" aria-controls="global-nav">
<span class="sr-only">メニューを開く</span>☰
</button>
<?php wp_nav_menu([
'theme_location' => 'global',
'container' => false,
'items_wrap' => '<ul id="global-nav" class="global-nav">%3$s</ul>',
]); ?>const toggle = document.querySelector('.menu-toggle');
const nav = document.getElementById('global-nav');
toggle?.addEventListener('click', () => {
const open = toggle.getAttribute('aria-expanded') === 'true';
toggle.setAttribute('aria-expanded', String(!open));
nav.classList.toggle('is-open');
});aria-expandedを切り替えておくと、支援技術にも開閉が伝わります。
メニューのHTMLを完全に自作する
wp_nav_menu()の出力に合わせるのが面倒なときは、項目データだけ取ってきて自分で組む方法があります。
<?php
$locations = get_nav_menu_locations();
$items = !empty($locations['global']) ? wp_get_nav_menu_items($locations['global']) : [];
?>
<?php if ($items) : ?>
<ul class="global-nav">
<?php foreach ($items as $item) : ?>
<?php if ((int) $item->menu_item_parent === 0) : ?>
<li>
<a href="<?php echo esc_url($item->url); ?>"><?php echo esc_html($item->title); ?></a>
</li>
<?php endif; ?>
<?php endforeach; ?>
</ul>
<?php endif; ?>menu_item_parentが0の項目が第1階層です。構造を完全に決められる代わりに、現在ページのclassなどは自分で付けることになります。
メニューを使わずページ一覧を出す
小さなサイトで「固定ページを自動で並べるだけ」なら、こちらのほうが手軽です。
<?php wp_list_pages(['title_li' => '', 'depth' => 1]); ?>ただし順番や表示するページを管理画面から選べないので、納品するサイトではメニュー機能を使うほうが親切です。
テーマ開発管理画面から編集できるナビメニューテーマ作りの流れの中で学びたいときは、テーマ開発コースのこの回へまとめ
register_nav_menus()で場所を登録し、wp_nav_menu()で呼び出す- 管理画面で「メニューの位置」にチェックを入れるまでは表示されない
- 余計なマークアップは
container: falseとitems_wrapで消せる current-menu-itemなどの自動classをCSSで使えば、強調やドロップダウンが作れる
メニューを管理画面から編集できる状態にしておくと、「リンクを1本足すだけ」の依頼が発生しなくなります。