custom wordpress menu with span for a links, div for drop down, streamlined ids and classes and titles

I am new to playing with WordPress functions and menu customizing and am wondering if a kind experienced user can please help me.

I would like to do the following for a menu called “Main” (its the primary menu):

1 add a span around the page title to top level items only (link_before and link_after attributes in the menu call don’t seem appropriate because they add to all menu items including sub pages)

2 add a wrapper div with class=drop around any sub menu ul’s (only around the first sub level, not sub sub level)

3a cleanup the WordPress ids and classes so that the only 3 classes are used on the li items – first, last, active

3b* add first and last classes to the li items

3c* with active applied down the chain – on the top level and the sub page as relevant (in the example below, you would be on Sub Page 2.1) (if possible)

4* add a title=”page name” in the “a links” if left empty in the Appearance/Menus setting for the page

*3b, 3c and 4 are nice to have but not a necessity

I would really like to do this via code in WP functions.php and the header.php files (not via javascript or css). Is that possible in WordPress? Is a “menu walker” the best solution?.

In my searching I have fumbled on something that does part of these things (1 and 3a) but they are quite old solutions (circa 2012) and not sure if they are still relevant to WordPress 4.7.4. Backwards compatibility with previous versions of WordPress is not required.

sample html

    <li class="first"><a href="#" title="Page 1"><span>Page 1</span></a></li>
    <li class="active"><a href="#" title="Page 2"><span>Page 2</span></a><div class="drop">
            <li class="first active"><a href="#" title="Sub Page 2.1">Sub Page 2.1</a></li>
            <li><a href="#" title="Sub Page 2.2">Sub Page 2.2</a></li>
            <li><a href="#" title="Sub Page 2.3">Sub Page 2.3</a></li>
            <li class="last"><a href="#" title="Sub Page 2.4">Sub Page 2.4</a></li>
    <li><a href="#" title="Page 3"><span>Page 3</span></a></li>
    <li><a href="#" title="Page 4"><span>Page 4</span></a><div class="drop">
            <li class="first"><a href="#" title="Sub Page 4.1">Sub Page 4.1</a></li>
            <li class="last"><a href="#" title="Sub Page 4.2">Sub Page 4.2</a></li>
    <li><a href="#" title="Page 5"><span>Page 5</span></a></li>
    <li><a href="#" title="Page 6"><span>Page 6</span></a></li>
    <li class="last"><a href="#" title="Page 7"><span>Page 7</span></a></li>

some code I found on stack overflow to cleanup classes – seems to work well
source: remove li class & id for menu items and pages list – from RevelationTravis 2012

//Deletes all CSS classes and id's, except for those listed in the array below
function custom_wp_nav_menu($var) {
    return is_array($var) ? array_intersect($var, array(
        //List of allowed menu classes
    ) : '';
add_filter('nav_menu_css_class', 'custom_wp_nav_menu');
add_filter('nav_menu_item_id', 'custom_wp_nav_menu');
add_filter('page_css_class', 'custom_wp_nav_menu');
//Replaces "current-menu-item" with "active"
function current_to_active($text){
    $replace = array(
        //List of menu item classes that should be changed to "active"
        'current_page_item' => 'active',
        'current_page_parent' => 'active',
        'current_page_ancestor' => 'active',
    $text = str_replace(array_keys($replace), $replace, $text);
        return $text;
add_filter ('wp_nav_menu','current_to_active');
//Deletes empty classes and removes the sub menu class
function strip_empty_classes($menu) {
    $menu = preg_replace('/ class=""| class="sub-menu"/','',$menu);
    return $menu;
add_filter ('wp_nav_menu','strip_empty_classes');

some code I found on stack overflow to add span to top level links only – but adds to all WP menus, not just to the menu called “main”

source: unknown

add_filter( 'wp_nav_menu_objects', function( $items ) {
      foreach ( $items as $item ) {
        if (!$item->menu_item_parent) {
           $item->title = '<span>' . $item->title . '</span>';
    return $items;

Any ideas?

Any help greatly appreciated.

Read more here: custom wordpress menu with span for a links, div for drop down, streamlined ids and classes and titles

Leave a Reply

Your email address will not be published. Required fields are marked *