wp_nav_menu change sub-menu class name?
Solution 1:
There is no option for this, but you can extend the 'walker' object that WordPress uses to create the menu HTML. Only one method needs to be overridden:
class My_Walker_Nav_Menu extends Walker_Nav_Menu {
function start_lvl(&$output, $depth) {
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul class=\"my-sub-menu\">\n";
}
}
Then you just pass an instance of your walker as an argument to wp_nav_menu
like so:
'walker' => new My_Walker_Nav_Menu()
Solution 2:
This is an old question and I'm not sure if the solution I'm going to mention was available by the time you asked, but I think it's worth mentioning. You can achieve what you want by adding a filter to nav_menu_submenu_css_class
. See the example below - you can replace my-new-submenu-class
by the class(es) you want:
function my_nav_menu_submenu_css_class( $classes ) {
$classes[] = 'my-new-submenu-class';
return $classes;
}
add_filter( 'nav_menu_submenu_css_class', 'my_nav_menu_submenu_css_class' );
Solution 3:
Choice of options.
- Switch the 'echo' argument to false and you can replace the class names.
echo str_replace('sub-menu', 'menu menu_sub', wp_nav_menu( array(
'echo' => false,
'theme_location' => 'sidebar-menu',
'items_wrap' => '<ul class="menu menu_sidebar">%3$s</ul>'
) )
);
- Since WP 4.8 we can use the nav_menu_submenu_css_class filter.
add_filter( 'nav_menu_submenu_css_class', 'my_custom_submenu_classnames', 10, 3 );
/**
* Filters the CSS class(es) applied to a menu list element.
*
* @param string[] $classes Array of the CSS classes that are applied to the menu `<ul>` element.
* @param stdClass $args An object of `wp_nav_menu()` arguments.
* @param int $depth Depth of menu item. Used for padding.
* @return string[]
*/
function my_custom_submenu_classnames( $classes, $args, $depth ) {
// Here we can additionally use menu arguments.
if ( 'header-menu' === $args->theme_location ) {
$default_class_name_key = array_search( 'sub-menu', $classes );
if ( false !== $default_class_name_key ) {
unset( $classes[ $default_class_name_key ] );
}
$classes[] = 'header-submenu';
$classes[] = "depth-{$depth}";
}
return $classes;
}
- Custom Menu walker:
class My_Nav_Menu_Walker extends Walker_Nav_Menu {
/**
* Starts the list before the elements are added.
*
* @see Walker::start_lvl()
*
* @param string $output Used to append additional content (passed by reference).
* @param int $depth Depth of menu item. Used for padding.
* @param stdClass $args An object of wp_nav_menu() arguments.
*/
public function start_lvl( &$output, $depth = 0, $args = null ) {
if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
$t = '';
$n = '';
} else {
$t = "\t";
$n = "\n";
}
$indent = str_repeat( $t, $depth );
// ! You default class names.
$classes = array( 'sub-menu', 'my-class' );
// ! Example of using arguments.
if ( 'header-menu' === $args->theme_location ) {
$default_class_name_key = array_search( 'sub-menu', $classes );
if ( false !== $default_class_name_key ) {
unset( $classes[ $default_class_name_key ] );
}
$classes[] = 'header-submenu';
$classes[] = "depth-{$depth}";
}
/**
* Filters the CSS class(es) applied to a menu list element.
*
* @since 4.8.0
*
* @param string[] $classes Array of the CSS classes that are applied to the menu `<ul>` element.
* @param stdClass $args An object of `wp_nav_menu()` arguments.
* @param int $depth Depth of menu item. Used for padding.
*/
$class_names = implode( ' ', apply_filters( 'nav_menu_submenu_css_class', $classes, $args, $depth ) );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
$output .= "{$n}{$indent}<ul{$class_names}>{$n}";
}
}
It remains to include the file with an custom walker and point it to the menu:
wp_nav_menu(
array(
'theme_location' => 'header-menu',
'walker' => new My_Nav_Menu_Walker()
)
);
Solution 4:
You can use WordPress preg_replace filter (in your theme functions.php file) example:
function new_submenu_class($menu) {
$menu = preg_replace('/ class="sub-menu"/','/ class="yourclass" /',$menu);
return $menu;
}
add_filter('wp_nav_menu','new_submenu_class');
Solution 5:
Here's an update to what Richard did that adds a "depth" indicator. The output is level-0, level-1, level-2, etc.
class UL_Class_Walker extends Walker_Nav_Menu {
function start_lvl(&$output, $depth) {
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul class=\"level-".$depth."\">\n";
}
}