Simple Navigation Walker – Wrapper-class around first sub-menu

I’m trying to wrap the first sub-menu of a navigation into a seperate div. None of the children or sub-levels should get the same treatment.

I’m really new to the Nav Walker-thingie and I’m really struggling and could need some help 😜

This is the structure I’m trying to achieve:

<ul class="menu">
    <li class="menu-item">
        <a href="#">Menu Item</a>
        <!-- wrapper-class around the first sub-menu -->
        <div class="sub-menu__wrapper">
            <ul class="sub-menu">
                <li class="menu-item">
                    <a href="#">Menu Item</a>
                    <!-- NO wrapper-class around following levels -->
                    <ul class="sub-menu">
                        <li>...</li>
                    </ul>
                </li>
            </ul>
        </div>
    </li>
</ul>

I thought it would be easy to do with a simple if-statement that only prints the sub-menu__wrapper on the first level, but somehow the following HTML-output gets mixed up pretty bad.

Here’s my Walker-class:

class sublevel_wrapper extends Walker_Nav_Menu {
    function start_lvl( &$output, $depth = 0, $args = array() ) {
        if ($depth == 0) {
            $output .= "<div class="sub-menu__wrapper"><ul class="sub-menu">\n";
        }
        //$output .= "<ul class="sub-menu">\n";
    }
    function end_lvl( &$output, $depth = 0, $args = array() ) {
        if ($depth == 0) {
            $output .= "</ul></div>\n";
        }
        //$output .= "</ul>\n";
    }
}

Which prints the following structure:

<ul class="menu">
    <li class="menu-item">
        <a href="#">Menu Item</a>
        <!-- wrapper-class around the first sub-menu -->
        <div class="sub-menu__wrapper">
            <ul class="sub-menu">
                <li class="menu-item">Parent Menu Item</li>
                <!-- the following items are supposed to be nested in the "parent menu item" before -->
                <li class="menu-item">Child Menu Item</li>
                <li class="menu-item">Child Menu Item</li>
                <li class="menu-item">Child Menu Item</li>
                <li class="menu-item">Parent Menu Item</li>
                <!-- again the following items are supposed to be nested in the "parent menu item" before -->
                <li class="menu-item">Child Menu Item</li>
                <li class="menu-item">Child Menu Item</li>
                <li class="menu-item">Child Menu Item</li>
                ...
            </ul>
        </div>
    </li>
</ul>

As you can see in the comments I tried to alter the output, if the if-statement is false, but that messes up the output even more 😂

Any help, constructive criticism or nudge in the right direction is much appreciated 🙇

2 Answers
2

To be honest, I don’t really know why my solution works, but it does 😂

I based my snippet on this solution and tweaked the output to my needs:
Custom nav walker with different output depending on depth

class sublevel_wrapper extends Walker_Nav_Menu {
    // add classes to ul sub-menus
    function start_lvl( &$output, $depth = 0, $args = array() ) {
        // depth dependent classes
        $indent = ( $depth > 0  ? str_repeat( "\t", $depth ) : '' ); // code indent
        $display_depth = ( $depth + 1); // because it counts the first submenu as 0
        $classes = array(
            'sub-menu',
            'menu-depth-' . $display_depth
        );
        $class_names = implode( ' ', $classes );

        // build html
        if ($display_depth == 1) {
            $output .= "\n" . $indent . '<div class="sub-menu__wrapper"><ul class="' . $class_names . '">' . "\n";
        } else {
            $output .= "\n" . $indent . '<ul class="' . $class_names . '">' . "\n";
        }
    }
}

Compared to my first snippet he leaves out the end_lvl-function completely and for whatever reason it worked. I also liked how he adds the $display_depth-variable.

Leave a Comment