How to build a custom Walker for WordPress menus
n WordPress, custom menus are essential when developing advanced themes. While the wp_nav_menu()function is flexible, there are cases where you need full control over the generated HTML. For those scenarios, WordPress provides the Walker_Nav_Menuclass, which you can extend to create a custom walker.
In this guide, we’ll cover:
- What is a Walker in WordPress?
- When to use a custom walker
- How to build your own walker step by step
- How to apply it to your menu
- Full working example
What is a Walker in WordPress?
A Walker is a class used by WordPress to loop through hierarchical data structures (like menus or nested taxonomies) and generate the appropriate HTML.
When using wp_nav_menu(), WordPress uses the Walker_Nav_Menuclass to create the HTML structure for , , and submenus.
To customize this structure, you can extend Walker_Nav_Menuand override certain methods to change the output.
When should you use a custom Walker?
You should create a custom walker when:
- You need to add custom classes or attributes to menu items.
- You want full control over the HTML structure of menus.
- You’re using a CSS framework like Bootstrap or Tailwind and need specific markup.
- You want to insert icons, s, or custom structures inside the menu.
Key methods to override
When extending
Walker_Nav_Menu, these are the most commonly overridden methods:) end_lvl() // Ends a submenu start_el() // Starts a menu item (
- ) end_el() // Ends a menu item
How to create a custom Walker
Create a file called
CustomMenuWalker.phpinside your theme or a plugin.\n"; } public function endLvl( &$output, $depth = 0, $args = [] ) { $indent = str_repeat( "\t", $depth ); $output .= "$indent\n"; } public function startEl( &$output, $item, $depth = 0, $args = [], $id = 0 ) { $indent = ( $depth ) ? str_repeat( "\t", $depth ) : ''; $classNames = implode( ' ', $item->classes ); $classAttr = $classNames ? ' class="' . esc_attr( $classNames ) . '"' : ''; $output .= "$indent- "; $title = apply_filters( 'the_title', $item->title, $item->ID ); $attributes = ' href="' . esc_attr( $item->url ) . '"'; $output .= ''; $output .= esc_html( $title ); $output .= ''; } public function endEl( &$output, $item, $depth = 0, $args = [] ) { $output .= "
\n"; } }How to use the Walker in wp_nav_menu()
Inside
header.phpor wherever you output the menu:'main_menu', 'container' => false, 'menu_class' => 'main-nav', 'walker' => new CustomMenuWalker() ]); ?>How to register the menu
In your
functions.phpfile or a plugin:'Main Menu' ]); } add_action( 'after_setup_theme', 'registerThemeMenus' );Suggested file structure
/wp-content/themes/your-theme/ │ ├── functions.php ├── header.php ├── inc/ │ └── CustomMenuWalker.php
And inside
functions.php, include the class:Example: Walker for Bootstrap 5
If you’re using Bootstrap, submenu
elements need the classdropdown-menu, and the parentelements should use the classdropdownwithdata-bs-toggle.Here’s a custom
startEl()for Bootstrap:classes ); $classes = $hasChildren ? 'dropdown' : ''; $output .= ' - ) end_el() // Ends a menu item
