Adding sections or headings to WordPress Menus – Making use of the walker_nav_menu_start_el filter

The WordPress menu builder makes it easy to add nested menu item links to a named menu, and display it in pre-defined theme location. However, as of writing in Jan 2019, there’s not an easy or built-in way to add menu sections or section headers. Here’s my solution:

The Design

Example visual to be recreated as a WordPress menu
Example visual to be recreated as a WordPress menu

The adjacent image shows the design that I’ve been asked to translate to a WordPress native menu. The orange items are page links. The white items are section headers and should not be active in any way. They are simply visual cues to aid navigation.

The Challenge

‘Out of the box’ WordPress doesn’t provide a place for menu section headers like ‘Services’ and ‘Products’ to be entered. It is possible to add them based on a menu item’s class or ID using the CSS ‘content’ property, or an absolutely positioned image, but this is tacky and hard-coded, so site owners and admins can’t easily change the menu section headers without a developer type person or some Additional CSS hackery.

We need to find a way of adding section headers that uses the WordPress menu builder and remains editable.

Hidden Options

In many WordPress admin screens there is a Screen Options link/tab/button, usually at the top right. The options available depend on the item being edited. In the Menu Builder, there are several ‘Advanced menu properties’ available, and the one we want is ‘Description’.

Description setting in Screen Options area
Description can be enabled under the ‘Screen Options’ tab in the edit screen.

Once ‘Description’ is selected, a new field will be available when editing a menu item. For our example design we want a section header called ‘Services’ to appear before the ‘Investigative Consulting’ menu item, so “Services” is entered into the description, and the menu us saved/published.

Description field in menu builder
Entering the desired section name in the newly activated Description field in the menu builder

The section head is now part of the menu object but without further theme modification, it won’t appear anywhere.

Theme Mods

Next we want to modify the WordPress theme to allow our description to show in the menu as a section header. To do this we’ll be editing the theme functions.php file.

Many articles aimed at modifying WordPress menu output suggest using a custom ‘walker’ class . This would work, but it’s overkill for what we’re doing. The walker_nav_menu class applies a filter called walker_nav_menu_start_el and that’s what we’re going to use instead.

The Code

The walker_nav_menu_start_el filter can edit each menu item’s “starting output” i.e. the menu link element (<a ... > </a> etc) and any ‘before’ and ‘after’ attributes which have been set when the menu is called. For a discussion of menu attributes, see the wp_nav_menu article.

By adding the following code to the functions.php file of the active theme a span containing the menu item’s Description is placed before the menu link when the menu is rendered:

// somewhere in the theme's functions.php file

function mqf_menu_descriptions( $item_output, $item, $depth, $args ){
    if ($depth == 0 && $item->description) {
        $item_output = '<span class="menu-item-description">' . $item->description . '</span>'.$item_output;
    }
    return $item_output;
}

add_filter( 'walker_nav_menu_start_el', 'mqf_menu_descriptions', 10, 4);

The if statement checks that the menu item is a top-level item with $depth == 0 and also that a description is set.

If this filter should only effect menus in certain locations, i.e. ‘primary’, then the if statement might look like this:

if ('primary' == $args->theme_location && $depth == 0 && $item->description) {

The Output

description output before the menu item but unstyled Now that the filter is added, when the menu is viewed it should output the description that’s been set immediately before the menu item. In the example we started with it appears as white text (see the adjacent image).

In order to style it up a bit, the following CSS improves things:

.section_description {
    display: block;
    text-transform: uppercase;
    font-size: 1.4rem;
    padding: 0.6rem 0 0.4rem;
    color: rgb(240, 240, 240);
}

The final result with some more section headers and menu items added is shown here:

Finished menu showing styled section headers
Finished menu showing styled section headers.

Hope that’s helped someone. If you have questions, corrections or criticisms please leave a comment below. Or just let me know what you thought with a click/tap on a thumb: Nope, not helpful...Yep, more useful than not! (No Ratings Yet)
Loading...

Leave a Reply

Your e-mail address will not be published. Required fields are marked *