nav_menu_link_attributesfilter-hookWP 3.6.0

Allows changing the <a> HTML attributes of a menu item: title, target, rel, and href.

By default, these attributes are configured in the menu editor in the admin panel:

The href attribute is the link. It is assigned automatically based on the selected item (post, category, and so on), or entered manually when a Custom Link item is selected.

Usage

add_filter( 'nav_menu_link_attributes', 'wp_kama_nav_menu_link_attributes_filter', 10, 4 );

/**
 * Function for `nav_menu_link_attributes` filter-hook.
 * 
 * @param array    $atts      The HTML attributes applied to the menu item's `<a>` element, empty
 *                            strings are ignored.
 * @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 array
 */
function wp_kama_nav_menu_link_attributes_filter( $atts, $menu_item, $args, $depth ){
	// filter...
	return $atts;
}
$atts(array)

HTML attributes for the menu item's <a> element. Attributes with empty values are not output.

  • $title(string)
    The title attribute. For example, "This item is very important."

  • $target(string)
    The target attribute. For example, _blank.

  • $rel(string)
    The rel attribute. For example, nofollow.

  • $href(string)
    The href attribute.
$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 Open external links in a separate tab

add_filter( 'nav_menu_link_attributes', 'change_nav_menu_link_attributes' );

function change_nav_menu_link_attributes( $atts ) {
	if ( strpos( $atts['href'], home_url() ) === false ) {
		$atts['target'] = '_blank';
	}

	return $atts;
}

#2 Add a class attribute to the active link

This example shows how you can extend the list of classes for a WordPress menu item and add your own class to the current active menu element.

// Add classes to links
add_filter( 'nav_menu_link_attributes', 'filter_nav_menu_link_attributes', 10, 4 );
function filter_nav_menu_link_attributes( $atts, $item, $args, $depth ) {

	if ( $item->current ) {
		$class = 'menu-link--active';
		$atts['class'] = isset( $atts['class'] ) ? "{$atts['class']} $class" : $class;
	}

	return $atts;
}

#3 Make all menu links relative

Remember that links to external sites must not be passed through wp_make_link_relative().

add_filter( 'nav_menu_link_attributes', 'change_nav_menu_atts', 10, 2 );
function change_nav_menu_atts( $atts, $item ) {
	$atts['href'] = str_replace( home_url(), '', $item->url );

	return $atts;
}

#4 Add attributes to links for opening a popup when clicked

Suppose a JavaScript script monitors links with the js-open-modal class. When one is clicked, the script reads its data-modal attribute and opens the popup with that number.

/**
 * Adds a class and popup number to menu links so the popup opens when clicked.
 * Assign modal-window-1 to a menu item in the admin panel to open popup #1.
 * Change the number to select a different popup.
 */
add_filter( 'nav_menu_link_attributes', function ( $atts, $menu_item ) {
	if ( empty( $menu_item->classes ) ) {
		return $atts;
	}

	foreach ( $menu_item->classes as $class ) {
		if ( strpos( $class, 'modal-window-' ) !== false ) {
			if ( isset( $atts['class'] ) ) {
				$atts['class'] .= ' js-open-modal';
			} else {
				$atts['class'] = 'js-open-modal';
			}

			$atts['data-modal'] = preg_replace( '/[^0-9]/', '', $class );

			break;
		}
	}

	return $atts;
}, 11, 2 );

Changelog

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

Where the hook is called

Walker_Nav_Menu::start_el()
nav_menu_link_attributes
wp-includes/class-walker-nav-menu.php 297
$atts       = apply_filters( 'nav_menu_link_attributes', $atts, $menu_item, $args, $depth );

Where the hook is used in WordPress

Usage not found.