nav_menu_css_classfilter-hookWP 3.0.0

Allows changing the set of CSS classes assigned to a menu item.

For details about how CSS classes are generated for menu items, see the wp_nav_menu() documentation.

Usage

add_filter( 'nav_menu_css_class', 'wp_kama_nav_menu_css_class_filter', 10, 4 );

/**
 * Function for `nav_menu_css_class` filter-hook.
 * 
 * @param string[] $classes   Array of the CSS classes that are applied to the menu item's `<li>` element.
 * @param WP_Post  $menu_item The current menu item object.
 * @param stdClass $args      An object of wp_nav_menu() arguments.
 * @param int      $depth     Depth of menu item. Used for padding.
 *
 * @return string[]
 */
function wp_kama_nav_menu_css_class_filter( $classes, $menu_item, $args, $depth ){

	// filter...
	return $classes;
}
$classes(array)

CSS classes applied to the menu item's <li> element. Example:

Array(
	[1] => menu-item
	[2] => menu-item-type-post_type
	[3] => menu-item-object-page
	[4] => menu-item-265
)
$item(WP_Post)

The current menu item object. Example:

WP_Post Object
(
	[ID] => 265
	[post_author] => 1
	[post_date] => 2018-04-07 09:45:46
	[post_date_gmt] => 2018-04-07 06:45:46
	[post_content] =>
	[post_title] => Contact
	[post_excerpt] =>
	[post_status] => publish
	[comment_status] => closed
	[ping_status] => closed
	[post_password] =>
	[post_name] => 265
	[to_ping] =>
	[pinged] =>
	[post_modified] => 2018-04-19 00:20:29
	[post_modified_gmt] => 2018-04-18 21:20:29
	[post_content_filtered] =>
	[post_parent] => 0
	[guid] => http://wp-test.ru/?p=265
	[menu_order] => 1
	[post_type] => nav_menu_item
	[post_mime_type] =>
	[comment_count] => 0
	[filter] => raw
	[db_id] => 265
	[menu_item_parent] => 0
	[object_id] => 214
	[object] => page
	[type] => post_type
	[type_label] => Page
	[url] => http://wp-test.ru/post-99
	[title] => Contact
	[target] =>
	[attr_title] =>
	[description] =>
	[classes] => Array
		(
			[0] =>
			[1] => menu-item
			[2] => menu-item-type-post_type
			[3] => menu-item-object-page
		)

	[xfn] =>
	[current] =>
	[current_item_ancestor] =>
	[current_item_parent] =>
)
$args(stdClass)

An object containing the arguments from wp_nav_menu(). Example:

stdClass Object
(
	[menu] => WP_Term Object
		(
			[term_id] => 21
			[name] => My first menu
			[slug] => my-first-menu
			[term_group] => 0
			[term_taxonomy_id] => 21
			[taxonomy] => nav_menu
			[description] =>
			[parent] => 0
			[count] => 3
			[filter] => raw
		)

	[container] => div
	[container_class] =>
	[container_id] =>
	[menu_class] => primary-menu
	[menu_id] =>
	[echo] => 1
	[fallback_cb] => wp_page_menu
	[before] =>
	[after] =>
	[link_before] =>
	[link_after] =>
	[items_wrap] => <ul id="%1$s" class="%2$s">%3$s</ul>
	[item_spacing] => preserve
	[depth] => 0
	[walker] =>
	[theme_location] => primary
)
$depth(int)
The menu item depth. Added in version 4.1.0 and used for indentation. Top-level menu items have $depth = 0, their children have $depth = 1, and so on.

Examples

#1 Remove CSS classes from all menu items

Remove all CSS classes from every menu item on the site.

add_filter( 'nav_menu_css_class', '__return_empty_array' );

The resulting markup:

<ul id="menu-my-first-menu" class="primary-menu">
	<li id="menu-item-265">
		<a href="http://wp-test.ru/post-99">Contact</a>
	</li>
	<li id="menu-item-266">
		<a href="http://wp-test.ru/post-98">All posts</a>
	</li>
	<li id="menu-item-267">
		<a href="http://wp-test.ru/post-97">Sitemap</a>
	</li>
</ul>

To remove or change the CSS id attribute of a menu item, use the nav_menu_item_id filter.

Conditions can also be used, as in the first example. Remove CSS classes from all menu items and add a custom CSS class to items in the primary menu location:

add_filter( 'nav_menu_css_class', 'change_menu_item_css_classes', 10, 4 );

function change_menu_item_css_classes( $classes, $item, $args, $depth ) {
	if ( 'primary' === $args->theme_location ) {
		$classes = [ 'my-css' ];
	} else {
		$classes = [];
	}

	return $classes;
}

The resulting markup:

<ul id="menu-my-first-menu" class="primary-menu">
	<li id="menu-item-265" class="my-css">
		<a href="http://wp-test.ru/post-99">Contact</a>
	</li>
	<li id="menu-item-266" class="my-css">
		<a href="http://wp-test.ru/post-98">All posts</a>
	</li>
	<li id="menu-item-267" class="my-css">
		<a href="http://wp-test.ru/post-97">Sitemap</a>
	</li>
</ul>

#2 Add a CSS class only to a particular menu item

Suppose the Contact menu item (ID 265) needs an additional CSS class, but only when it is displayed in a menu assigned to the primary location:

add_filter( 'nav_menu_css_class', 'change_menu_item_css_classes', 10, 4 );

function change_menu_item_css_classes( $classes, $item, $args, $depth ) {
	if( 265 === $item->ID  && 'primary' === $args->theme_location ){
		$classes[] = 'special-css-class';
	}

	return $classes;
}

The resulting markup:

<ul id="menu-my-first-menu" class="primary-menu">
	<li id="menu-item-265" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-265 special-css-class">
		<a href="http://wp-test.ru/post-99">Contact</a>
	</li>
	<li id="menu-item-266" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-266">
		<a href="http://wp-test.ru/post-98">All posts</a>
	</li>
	<li id="menu-item-267" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-267">
		<a href="http://wp-test.ru/post-97">Sitemap</a>
	</li>
</ul>

Notes

  • The $depth parameter was added in version 4.1.0.

Changelog

Since 3.0.0 Introduced.
Since 4.1.0 The $depth parameter was added.

Where the hook is called

Walker_Nav_Menu::start_el()
nav_menu_css_class
wp-includes/class-walker-nav-menu.php 194
$class_names = implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $menu_item, $args, $depth ) );

Where the hook is used in WordPress

wp-includes/default-filters.php 705
add_filter( 'nav_menu_css_class', 'wp_nav_menu_remove_menu_item_has_children_class', 10, 4 );