WordPress navigation menus are one of the first things you set up in any theme. You register locations in functions.php, let the admin assign menus to those locations, and then render them in templates. Here’s the full flow.
Problem: How do you register custom navigation menu locations in a WordPress theme and output them in templates?
Solution: Call register_nav_menus() inside after_setup_theme to declare locations, then use wp_nav_menu() in your templates to render them with the correct menu assigned.
Register menu locations in functions.php:
add_action( 'init', 'register_my_menus' );
function register_my_menus() {
register_nav_menus( [
'primary' => __( 'Primary Menu', 'textdomain' ),
'footer' => __( 'Footer Menu', 'textdomain' ),
'mobile' => __( 'Mobile Menu', 'textdomain' ),
] );
}
Render a menu in a template file:
wp_nav_menu( [
'theme_location' => 'primary',
'menu_class' => 'nav-menu',
'container' => 'nav',
'container_class'=> 'site-nav',
'depth' => 2,
'fallback_cb' => false, // don't fall back to page list if no menu assigned
] );
To add a custom CSS class to a specific menu item without a plugin, use the nav_menu_css_class filter:
add_filter( 'nav_menu_css_class', 'add_menu_item_class', 10, 3 );
function add_menu_item_class( $classes, $item, $args ) {
if ( 'primary' === $args->theme_location && $item->current ) {
$classes[] = 'is-active';
}
return $classes;
}
NOTE: The depth argument controls how many levels of sub-menus are rendered — set it to 0 for unlimited depth. Use fallback_cb => false in production to prevent a raw page list from appearing if no menu has been assigned to the location.