Creating a smooth, responsive mobile navigation that supports second- and third-level submenus can be tricky.
Below is a complete example using a custom Walker_Nav_Menu class, tailored HTML markup, CSS transitions, and a little jQuery to give users an elegant slide/accordion experience.
1. PHP: Custom Walker
Place this in your theme (e.g. in functions.php or a dedicated class-mobile-walker.php):
class Mobile_Walker_Nav_Menu extends Walker_Nav_Menu {
// Start <ul>
function start_lvl( &$output, $depth = 0, $args = null ) {
$indent = str_repeat("\t", $depth);
$classes = $depth === 0 ? 'submenu' : 'third-submenu';
$output .= "\n$indent<ul class=\"$classes\">\n";
}
// Start <li>
function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) {
$indent = $depth ? str_repeat("\t", $depth) : '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = 'nav-list__item';
$class_names = join( ' ', array_filter( $classes ) );
$has_children = in_array( 'menu-item-has-children', $classes, true );
$trigger_class = $has_children
? ( $depth === 0 ? ' submenu--trigger' : ' third-submenu--trigger' )
: '';
$output .= $indent . '<li class="' . esc_attr( $class_names . $trigger_class ) . '">';
$atts = array(
'href' => ! empty( $item->url ) ? $item->url : '',
'class' => 'nav-link',
);
$attributes = '';
foreach ( $atts as $attr => $value ) {
if ( ! empty( $value ) ) {
$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
$attributes .= ' ' . $attr . '="' . $value . '"';
}
}
$item_output = '<a' . $attributes . '>';
$item_output .= apply_filters( 'the_title', $item->title, $item->ID );
if ( $has_children ) {
$item_output .= '<i class="caret-down-icon"></i>';
}
$item_output .= '</a>';
$output .= $item_output;
}
}
2. Header Markup
Insert this in your header template where the mobile menu should appear:
3. CSS Styling
Add to your theme’s main stylesheet or a custom CSS file:
4. jQuery Toggle Script
Enqueue this via your theme’s JS file:
Wrap-Up
With the Mobile_Walker_Nav_Menu class and the CSS/JS above, you’ll have a clean, multi-level mobile menu that expands on caret click and keeps parent links functional.