WordPress 3.0+ 引入選單系統,讓使用者可在後台拖曳建立導航選單。開發者需先在主題 functions.php 註冊選單位置,再在模板中呼叫輸出。本文完整解析 register_nav_menus() 與 wp_nav_menu() 的參數、範例與進階技巧。
register_nav_menus( array $locations )
$locations:關聯陣列,Key 為選單識別碼,Value 為顯示名稱(支援多國語系 __())function my_theme_register_menus() {
register_nav_menus(array(
'header_menu' => __('頂部導航', 'my-theme'),
'footer_menu' => __('頁腳導航', 'my-theme'),
'social_menu' => __('社群連結', 'my-theme'),
));
}
add_action('init', 'my_theme_register_menus');
註冊後,後台「外觀 → 選單」即可建立選單並指派至上述位置。
wp_nav_menu( array $args = array() )
| 參數 | 型別 | 預設值 | 說明 |
|---|---|---|---|
| theme_location | string | '' | 對應註冊時的 Key(如 header_menu) |
| menu | string | '' | 指定選單 ID、slug 或名稱(優先級高於 theme_location) |
| container | string | 'div' | 外層容器標籤:div、nav、false(不輸出容器) |
| container_class | string | 'menu-{slug}-container' | 容器 class |
| container_id | string | '' | 容器 id |
| menu_class | string | 'menu' | <ul> 的 class |
| menu_id | string | 選單 slug | <ul> 的 id |
| echo | bool | true | true=直接輸出,false=回傳字串 |
| fallback_cb | callable | 'wp_page_menu' | 找不到選單時的回調函數 |
| before | string | '' | 每個 <a> 之前的文字 |
| after | string | '' | 每個 <a> 之後的文字 |
| link_before | string | '' | 連結文字之前的文字 |
| link_after | string | '' | 連結文字之後的文字 |
| items_wrap | string | '<ul id="%1$s" class="%2$s">%3$s</ul>' | 包裹項目的模板,%1$s=id, %2$s=class, %3$s=items |
| depth | int | 0 | 顯示層級深度,0=全部 |
| walker | object | Walker_Nav_Menu | 自訂 Walker 類別 |
wp_nav_menu(array(
'theme_location' => 'header_menu',
'container' => false,
'items_wrap' => '',
'fallback_cb' => 'my_fallback_menu',
));
function my_fallback_menu() {
echo '';
}
<nav> 容器、加入 BEM 命名wp_nav_menu(array(
'theme_location' => 'header_menu',
'container' => 'nav',
'container_class' => 'site-nav',
'menu_class' => 'site-nav__list',
'menu_id' => 'site-nav-list',
'depth' => 2, // 僅顯示兩層
));
$menuHtml = wp_nav_menu(array(
'theme_location' => 'footer_menu',
'echo' => false,
'container' => false,
));
// 可對 $menuHtml 進行字串替換、快取等操作
echo $menuHtml;
add_filter('nav_menu_css_class', function($classes, $item, $args, $depth) {
if (in_array('current-menu-item', $classes) || in_array('current-menu-ancestor', $classes)) {
$classes[] = 'is-active';
}
return $classes;
}, 10, 4);
class My_Walker extends Walker_Nav_Menu {
function start_lvl(&$output, $depth = 0, $args = []) {
$indent = str_repeat("\t", $depth);
$output .= "\n$indentadd_filter('walker_nav_menu_start_el', function($item_output, $item, $depth, $args) {
if ($item->attr_title) { // 在後台選單項目「標題屬性」填入圖示 class
$item_output = str_replace(' ', $item_output);
}
return $item_output;
}, 10, 4);
| 問題 | 解答 |
|---|---|
| 選單不顯示 | 確認 theme_location 拼寫正確、後台已指派選單、模板位置正確 |
| 想移除外層 <div> | 設定 'container' => false |
| 需在選單加入搜尋框/登入連結 | 使用 'items_wrap' 或 'wp_nav_menu_items' filter 動態插入 |
| 多語系網站選單不同 | 搭配 Polylang/WPML,註冊不同 location 或使用 menu 參數指定 |
register_nav_menus() 定義「位置」,wp_nav_menu() 輸出「內容」。掌握參數陣列與 Filter/Hook,即可實現從簡單導航到複雜 Mega Menu 的彈性客製化。