如何在WordPress中通过has_nav_menu实现子菜单样式生效?
实现WordPress菜单匹配自定义HTML样式的方法
问题背景
你有一套带样式类的菜单HTML结构,希望通过WordPress的wp_nav_menu函数输出对应结构,让预设样式生效。
参考HTML结构
<ul class="align-items-center d-flex"> <li class="nav-item dropdown mx-2"> <a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">Home</a> <ul class="dropdown-menu"> <li><a class="dropdown-item" href="#">Home 1</a></li> <li><a class="dropdown-item" href="#">Home 2</a></li> </ul> </li> <li class="mx-2"><a href="#">About</a></li> </ul>
原WordPress菜单PHP代码
<?php if (has_nav_menu('header_menu')) { wp_nav_menu( array( 'theme_location' => 'header_menu', 'items_wrap' => '%3$s', 'fallback_cb' => false, 'container' => false, ) ); } ?>
解决方法
要让WordPress输出和参考HTML一致的结构,需要调整wp_nav_menu参数并添加自定义类的处理逻辑:
修改后的完整PHP代码
<?php if (has_nav_menu('header_menu')) { wp_nav_menu( array( 'theme_location' => 'header_menu', 'container' => false, 'items_wrap' => '<ul class="align-items-center d-flex">%3$s</ul>', 'fallback_cb' => false, 'walker' => new Custom_Nav_Walker() ) ); } // 自定义导航Walker类,处理下拉菜单和链接类 class Custom_Nav_Walker extends Walker_Nav_Menu { // 处理菜单项的开始标签 function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) { $classes = empty($item->classes) ? array() : (array)$item->classes; // 给顶级菜单项添加基础类 if ($depth === 0) { $classes[] = 'nav-item mx-2'; // 带子菜单的项添加dropdown类 if (in_array('menu-item-has-children', $classes)) { $classes[] = 'dropdown'; } } // 下拉子项添加dropdown-item类 if ($depth === 1) { $classes[] = 'dropdown-item'; } $class_names = implode(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item, $args)); $class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : ''; $output .= "<li$class_names>"; $atts = array(); $atts['href'] = !empty($item->url) ? $item->url : ''; // 处理顶级下拉菜单的链接属性 if ($depth === 0 && in_array('menu-item-has-children', $item->classes)) { $atts['class'] = 'nav-link dropdown-toggle'; $atts['data-bs-toggle'] = 'dropdown'; $atts['role'] = 'button'; $atts['aria-expanded'] = 'false'; } elseif ($depth === 0) { // 普通顶级链接类 $atts['class'] = 'nav-link'; } $atts = apply_filters('nav_menu_link_attributes', $atts, $item, $args); $attributes = ''; foreach ($atts as $attr => $value) { if (!empty($value)) { $value = ('href' === $attr) ? esc_url($value) : esc_attr($value); $attributes .= ' ' . $attr . '="' . $value . '"'; } } $title = apply_filters('the_title', $item->title, $item->ID); $title = apply_filters('nav_menu_item_title', $title, $item, $args, $depth); $item_output = $args->before; $item_output .= '<a' . $attributes . '>'; $item_output .= $args->link_before . $title . $args->link_after; $item_output .= '</a>'; $item_output .= $args->after; $output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args); } // 处理下拉菜单的开始标签 function start_lvl(&$output, $depth = 0, $args = null) { if ($depth === 0) { $output .= '<ul class="dropdown-menu">'; } } } ?>
代码说明
- 外层ul类设置:通过
items_wrap参数给外层ul直接添加align-items-center d-flex类,补全ul标签结构。 - 自定义Walker类:
- 给顶级菜单项添加
nav-item mx-2类,带子菜单的项额外添加dropdown类。 - 给顶级下拉菜单的链接添加
nav-link dropdown-toggle及Bootstrap下拉所需的交互属性。 - 自动给下拉子菜单的链接添加
dropdown-item类,同时生成带dropdown-menu类的子ul。
- 给顶级菜单项添加
- 移除容器:保持
container => false,避免WordPress自动生成多余的div容器。
额外注意事项
- 确保主题已引入Bootstrap的CSS和JS文件,否则下拉菜单的样式和交互无法正常工作。
- 在WordPress后台「外观-菜单」中,给需要作为下拉菜单的父项启用下拉功能,确保
menu-item-has-children类被自动添加。
内容的提问来源于stack exchange,提问作者soltaneghalbha
相关产品推荐
相关产品推荐

