Add Navigation Dividers With wp_nav_menu Without Trailing Divider

WP_Nav_Menu is an excellent addition to WordPress, allowing clients to quickly edit navigation menus so developers don’t have to be on call to change simple links. The biggest flaw of using it is the markup: there aren’t specific CSS classes to mark first and last menu items. This is a problem when your design calls for dividers between each menu item.

Your typical usage of wp_nav_menu and dividers might look like this:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
 
    $divider = '<div class="nav-divider"> | </div>';
    wp_nav_menu(
        array(
              'container_class' => 'menu-header',
              'menu'            => 'Test Menu',
              'theme_location'  => 'primary',
              'link_after'      => $divider
            )
    );
?>
<?php

    $divider = '<div class="nav-divider"> | </div>';
    wp_nav_menu(
        array(
              'container_class' => 'menu-header',
              'menu'            => 'Test Menu',
              'theme_location'  => 'primary',
              'link_after'      => $divider
            )
    );
?>

Using the basic TwentyTen theme, this is what the end result looks like:

Of course the easy solution would be to go to the menu editor and manually add a CSS class to the last menu item. That’s poor design because the last menu item is subject to change as the client sees fit.

Instead let’s dynamically add the CSS class using a custom function in the functions.php file:

1
2
3
4
5
6
7
8
9
10
11
12
13
function nav_menu_classes( $items ) {
    // Find the last menu item and append
    //  custom class before 'menu-item' class
    $pos = strrpos($items, 'class="menu-item', -1);
    $items=substr_replace($items, 'menu-item-last ', $pos+7, 0);
 
    // Find first menu item and do same thing
    $pos = strpos($items, 'class="menu-item');
    $items=substr_replace($items, 'menu-item-first ', $pos+7, 0);
 
    return $items;
}
add_filter( 'wp_nav_menu_items', 'nav_menu_classes' );
function nav_menu_classes( $items ) {
    // Find the last menu item and append
    //  custom class before 'menu-item' class
    $pos = strrpos($items, 'class="menu-item', -1);
    $items=substr_replace($items, 'menu-item-last ', $pos+7, 0);

    // Find first menu item and do same thing
    $pos = strpos($items, 'class="menu-item');
    $items=substr_replace($items, 'menu-item-first ', $pos+7, 0);

    return $items;
}
add_filter( 'wp_nav_menu_items', 'nav_menu_classes' );

This gives us two new unique CSS classes to work with. For our purpose we will simply not display the nav-divider class when it is a child of the menu-item-last class.

1
.menu-item-last .nav-divider {display:none;}
.menu-item-last .nav-divider {display:none;}

And finally the expected result:

Discussion
Steve says:

Hi , how do I call the function?

do I put it in header.php?

Thanks

Zachary Schuessler says:

No need to call any extra function. Just call the wp_nav_menu() like I did in the first code block 😉

James says:

Thanks for this. The problem with it, though, is that the separators should not be part of the link… Can you find a solution using ‘after’ instead of ‘link_after’ ?

nasim says:

that works perfectly, but a there is e question of direction of menu items in multi language sites!
The problem is when I did what you said it worked properly in my pages with direction:rtl(for Persian language pages) and direction:ltr(for English language pages). but when I add Persian and English item mixed in my menu it doesn’t work properly ONLY in firefox eventhough the direction of body was rtl!and i tried to fix it with direction or text-align in css class of menu item but no change have happend.

Leave a Reply