If you are looking for a way to have a clean navigation list without the default classes and ids then the simplest solution I found is to extend the Walker class with a modified version of the Walker_Nav_Menu
class.
The code below is for my custom Walker
which is actually the same code as the navigation Walker shipped with WordPress minus the echo of default CSS classes and ids. To make this work simply drop the code in your theme’s functions.php
.
<?php class MV_Cleaner_Walker_Nav_Menu extends Walker { var $tree_type = array( 'post_type', 'taxonomy', 'custom' ); var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' ); function start_lvl(&$output, $depth) { $indent = str_repeat("\t", $depth); $output .= "\n$indent<ul class=\"sub-menu\">\n"; } function end_lvl(&$output, $depth) { $indent = str_repeat("\t", $depth); $output .= "$indent</ul>\n"; } function start_el(&$output, $item, $depth, $args) { global $wp_query; $indent = ( $depth ) ? str_repeat( "\t", $depth ) : ''; $class_names = $value = ''; $classes = empty( $item->classes ) ? array() : (array) $item->classes; $classes = in_array( 'current-menu-item', $classes ) ? array( 'current-menu-item' ) : array(); $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) ); $class_names = strlen( trim( $class_names ) ) > 0 ? ' class="' . esc_attr( $class_names ) . '"' : ''; $id = apply_filters( 'nav_menu_item_id', '', $item, $args ); $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : ''; $output .= $indent . '<li' . $id . $value . $class_names .'>'; $attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) .'"' : ''; $attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) .'"' : ''; $attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) .'"' : ''; $attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : ''; $item_output = $args->before; $item_output .= '<a'. $attributes .'>'; $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after; $item_output .= '</a>'; $item_output .= $args->after; $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args ); } function end_el(&$output, $item, $depth) { $output .= "</li>\n"; } } ?>
Then make sure to specify the new custom Walker when calling wp_nav_menu()
.
<?php wp_nav_menu( array( 'walker' => new MV_Cleaner_Walker_Nav_Menu() ) ); ?>
Example:
<ul id="menu-main" class="menu"> <li><a href="https://mattvarone.com/about/">About</a></li> <li><a href="https://mattvarone.com/featured-content/">Featured</a></li> <li><a href="https://mattvarone.com/contact/">Contact</a></li> <li><a href="https://mattvarone.com/blog/">Blog</a></li> </ul>
What if you’d like to add your own classes afterwards?
Hi Shaun,
I brought back the
nav_menu_css_class
andnav_menu_item_id
filters. You can use these optionally to add classes and id’s.For example:
Would output:
Thank you for this. It’s been a big help. However, when clicking on a menu item, wordpress no longer attaches the ‘current-menu-item’ class. Any word on how to restore that and keep the clean markup?
Thanks.
Yes, my question is the same. How it’s possible to allow the ‘current-menu-item’ class?
This is great, but I also remove sub-menus, how I utilize this and have sub-menus as well?
Class updated, now it adds
‘current-menu-item’
.use:
$current_url = (is_ssl()?’https://’:’http://’).$_SERVER[‘HTTP_HOST’].$_SERVER[‘REQUEST_URI’];
$item_url = esc_attr( $item->url );
if ( $item_url == $current_url ){
$attributes .= ‘bla-bla-bla’;
}