Title: _wp_menu_item_classes_by_context
Published: April 25, 2014
Last modified: April 28, 2025

---

# _wp_menu_item_classes_by_context( array $menu_items )

## In this article

 * [Parameters](https://developer.wordpress.org/reference/functions/_wp_menu_item_classes_by_context/?output_format=md#parameters)
 * [Source](https://developer.wordpress.org/reference/functions/_wp_menu_item_classes_by_context/?output_format=md#source)
 * [Related](https://developer.wordpress.org/reference/functions/_wp_menu_item_classes_by_context/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/functions/_wp_menu_item_classes_by_context/?output_format=md#changelog)

[ Back to top](https://developer.wordpress.org/reference/functions/_wp_menu_item_classes_by_context/?output_format=md#wp--skip-link--target)

This function’s access is marked private. This means it is not intended for use 
by plugin or theme developers, only by core. It is listed here for completeness.

Adds the class property classes for the current context, if applicable.

## 󠀁[Parameters](https://developer.wordpress.org/reference/functions/_wp_menu_item_classes_by_context/?output_format=md#parameters)󠁿

 `$menu_items`arrayrequired

The current menu item objects to which to add the class property information.

## 󠀁[Source](https://developer.wordpress.org/reference/functions/_wp_menu_item_classes_by_context/?output_format=md#source)󠁿

    ```php
    function _wp_menu_item_classes_by_context( &$menu_items ) {
    	global $wp_query, $wp_rewrite;

    	$queried_object    = $wp_query->get_queried_object();
    	$queried_object_id = (int) $wp_query->queried_object_id;

    	$active_object               = '';
    	$active_ancestor_item_ids    = array();
    	$active_parent_item_ids      = array();
    	$active_parent_object_ids    = array();
    	$possible_taxonomy_ancestors = array();
    	$possible_object_parents     = array();
    	$home_page_id                = (int) get_option( 'page_for_posts' );

    	if ( $wp_query->is_singular && ! empty( $queried_object->post_type ) && ! is_post_type_hierarchical( $queried_object->post_type ) ) {
    		foreach ( (array) get_object_taxonomies( $queried_object->post_type ) as $taxonomy ) {
    			if ( is_taxonomy_hierarchical( $taxonomy ) ) {
    				$term_hierarchy = _get_term_hierarchy( $taxonomy );
    				$terms          = wp_get_object_terms( $queried_object_id, $taxonomy, array( 'fields' => 'ids' ) );
    				if ( is_array( $terms ) ) {
    					$possible_object_parents = array_merge( $possible_object_parents, $terms );
    					$term_to_ancestor        = array();
    					foreach ( (array) $term_hierarchy as $ancestor => $descendents ) {
    						foreach ( (array) $descendents as $desc ) {
    							$term_to_ancestor[ $desc ] = $ancestor;
    						}
    					}

    					foreach ( $terms as $desc ) {
    						do {
    							$possible_taxonomy_ancestors[ $taxonomy ][] = $desc;
    							if ( isset( $term_to_ancestor[ $desc ] ) ) {
    								$_desc = $term_to_ancestor[ $desc ];
    								unset( $term_to_ancestor[ $desc ] );
    								$desc = $_desc;
    							} else {
    								$desc = 0;
    							}
    						} while ( ! empty( $desc ) );
    					}
    				}
    			}
    		}
    	} elseif ( ! empty( $queried_object->taxonomy ) && is_taxonomy_hierarchical( $queried_object->taxonomy ) ) {
    		$term_hierarchy   = _get_term_hierarchy( $queried_object->taxonomy );
    		$term_to_ancestor = array();
    		foreach ( (array) $term_hierarchy as $ancestor => $descendents ) {
    			foreach ( (array) $descendents as $desc ) {
    				$term_to_ancestor[ $desc ] = $ancestor;
    			}
    		}
    		$desc = $queried_object->term_id;
    		do {
    			$possible_taxonomy_ancestors[ $queried_object->taxonomy ][] = $desc;
    			if ( isset( $term_to_ancestor[ $desc ] ) ) {
    				$_desc = $term_to_ancestor[ $desc ];
    				unset( $term_to_ancestor[ $desc ] );
    				$desc = $_desc;
    			} else {
    				$desc = 0;
    			}
    		} while ( ! empty( $desc ) );
    	}

    	$possible_object_parents = array_filter( $possible_object_parents );

    	$front_page_url         = home_url();
    	$front_page_id          = (int) get_option( 'page_on_front' );
    	$privacy_policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );

    	foreach ( (array) $menu_items as $key => $menu_item ) {

    		$menu_items[ $key ]->current = false;

    		$classes   = (array) $menu_item->classes;
    		$classes[] = 'menu-item';
    		$classes[] = 'menu-item-type-' . $menu_item->type;
    		$classes[] = 'menu-item-object-' . $menu_item->object;

    		// This menu item is set as the 'Front Page'.
    		if ( 'post_type' === $menu_item->type && $front_page_id === (int) $menu_item->object_id ) {
    			$classes[] = 'menu-item-home';
    		}

    		// This menu item is set as the 'Privacy Policy Page'.
    		if ( 'post_type' === $menu_item->type && $privacy_policy_page_id === (int) $menu_item->object_id ) {
    			$classes[] = 'menu-item-privacy-policy';
    		}

    		// If the menu item corresponds to a taxonomy term for the currently queried non-hierarchical post object.
    		if ( $wp_query->is_singular && 'taxonomy' === $menu_item->type
    			&& in_array( (int) $menu_item->object_id, $possible_object_parents, true )
    		) {
    			$active_parent_object_ids[] = (int) $menu_item->object_id;
    			$active_parent_item_ids[]   = (int) $menu_item->db_id;
    			$active_object              = $queried_object->post_type;

    			// If the menu item corresponds to the currently queried post or taxonomy object.
    		} elseif (
    			(int) $menu_item->object_id === $queried_object_id
    			&& (
    				( ! empty( $home_page_id ) && 'post_type' === $menu_item->type
    					&& $wp_query->is_home && $home_page_id === (int) $menu_item->object_id )
    				|| ( 'post_type' === $menu_item->type && $wp_query->is_singular )
    				|| ( 'taxonomy' === $menu_item->type
    					&& ( $wp_query->is_category || $wp_query->is_tag || $wp_query->is_tax )
    					&& $queried_object->taxonomy === $menu_item->object )
    			)
    		) {
    			$classes[]                   = 'current-menu-item';
    			$menu_items[ $key ]->current = true;
    			$ancestor_id                 = (int) $menu_item->db_id;

    			while (
    				( $ancestor_id = (int) get_post_meta( $ancestor_id, '_menu_item_menu_item_parent', true ) )
    				&& ! in_array( $ancestor_id, $active_ancestor_item_ids, true )
    			) {
    				$active_ancestor_item_ids[] = $ancestor_id;
    			}

    			if ( 'post_type' === $menu_item->type && 'page' === $menu_item->object ) {
    				// Back compat classes for pages to match wp_page_menu().
    				$classes[] = 'page_item';
    				$classes[] = 'page-item-' . $menu_item->object_id;
    				$classes[] = 'current_page_item';
    			}

    			$active_parent_item_ids[]   = (int) $menu_item->menu_item_parent;
    			$active_parent_object_ids[] = (int) $menu_item->post_parent;
    			$active_object              = $menu_item->object;

    			// If the menu item corresponds to the currently queried post type archive.
    		} elseif (
    			'post_type_archive' === $menu_item->type
    			&& is_post_type_archive( array( $menu_item->object ) )
    		) {
    			$classes[]                   = 'current-menu-item';
    			$menu_items[ $key ]->current = true;
    			$ancestor_id                 = (int) $menu_item->db_id;

    			while (
    				( $ancestor_id = (int) get_post_meta( $ancestor_id, '_menu_item_menu_item_parent', true ) )
    				&& ! in_array( $ancestor_id, $active_ancestor_item_ids, true )
    			) {
    				$active_ancestor_item_ids[] = $ancestor_id;
    			}

    			$active_parent_item_ids[] = (int) $menu_item->menu_item_parent;

    			// If the menu item corresponds to the currently requested URL.
    		} elseif ( 'custom' === $menu_item->object && isset( $_SERVER['HTTP_HOST'] ) ) {
    			$_root_relative_current = untrailingslashit( $_SERVER['REQUEST_URI'] );

    			// If it's the customize page then it will strip the query var off the URL before entering the comparison block.
    			if ( is_customize_preview() ) {
    				$_root_relative_current = strtok( untrailingslashit( $_SERVER['REQUEST_URI'] ), '?' );
    			}

    			$current_url        = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_root_relative_current );
    			$raw_item_url       = strpos( $menu_item->url, '#' ) ? substr( $menu_item->url, 0, strpos( $menu_item->url, '#' ) ) : $menu_item->url;
    			$item_url           = set_url_scheme( untrailingslashit( $raw_item_url ) );
    			$_indexless_current = untrailingslashit( preg_replace( '/' . preg_quote( $wp_rewrite->index, '/' ) . '$/', '', $current_url ) );

    			$matches = array(
    				$current_url,
    				urldecode( $current_url ),
    				$_indexless_current,
    				urldecode( $_indexless_current ),
    				$_root_relative_current,
    				urldecode( $_root_relative_current ),
    			);

    			if ( $raw_item_url && in_array( $item_url, $matches, true ) ) {
    				$classes[]                   = 'current-menu-item';
    				$menu_items[ $key ]->current = true;
    				$ancestor_id                 = (int) $menu_item->db_id;

    				while (
    					( $ancestor_id = (int) get_post_meta( $ancestor_id, '_menu_item_menu_item_parent', true ) )
    					&& ! in_array( $ancestor_id, $active_ancestor_item_ids, true )
    				) {
    					$active_ancestor_item_ids[] = $ancestor_id;
    				}

    				if ( in_array( home_url(), array( untrailingslashit( $current_url ), untrailingslashit( $_indexless_current ) ), true ) ) {
    					// Back compat for home link to match wp_page_menu().
    					$classes[] = 'current_page_item';
    				}
    				$active_parent_item_ids[]   = (int) $menu_item->menu_item_parent;
    				$active_parent_object_ids[] = (int) $menu_item->post_parent;
    				$active_object              = $menu_item->object;

    				// Give front page item the 'current-menu-item' class when extra query arguments are involved.
    			} elseif ( $item_url === $front_page_url && is_front_page() ) {
    				$classes[] = 'current-menu-item';
    			}

    			if ( untrailingslashit( $item_url ) === home_url() ) {
    				$classes[] = 'menu-item-home';
    			}
    		}

    		// Back-compat with wp_page_menu(): add "current_page_parent" to static home page link for any non-page query.
    		if ( ! empty( $home_page_id ) && 'post_type' === $menu_item->type
    			&& empty( $wp_query->is_page ) && $home_page_id === (int) $menu_item->object_id
    		) {
    			$classes[] = 'current_page_parent';
    		}

    		$menu_items[ $key ]->classes = array_unique( $classes );
    	}
    	$active_ancestor_item_ids = array_filter( array_unique( $active_ancestor_item_ids ) );
    	$active_parent_item_ids   = array_filter( array_unique( $active_parent_item_ids ) );
    	$active_parent_object_ids = array_filter( array_unique( $active_parent_object_ids ) );

    	// Set parent's class.
    	foreach ( (array) $menu_items as $key => $parent_item ) {
    		$classes                                   = (array) $parent_item->classes;
    		$menu_items[ $key ]->current_item_ancestor = false;
    		$menu_items[ $key ]->current_item_parent   = false;

    		if (
    			isset( $parent_item->type )
    			&& (
    				// Ancestral post object.
    				(
    					'post_type' === $parent_item->type
    					&& ! empty( $queried_object->post_type )
    					&& is_post_type_hierarchical( $queried_object->post_type )
    					&& in_array( (int) $parent_item->object_id, $queried_object->ancestors, true )
    					&& (int) $parent_item->object_id !== $queried_object->ID
    				) ||

    				// Ancestral term.
    				(
    					'taxonomy' === $parent_item->type
    					&& isset( $possible_taxonomy_ancestors[ $parent_item->object ] )
    					&& in_array( (int) $parent_item->object_id, $possible_taxonomy_ancestors[ $parent_item->object ], true )
    					&& (
    						! isset( $queried_object->term_id ) ||
    						(int) $parent_item->object_id !== $queried_object->term_id
    					)
    				)
    			)
    		) {
    			if ( ! empty( $queried_object->taxonomy ) ) {
    				$classes[] = 'current-' . $queried_object->taxonomy . '-ancestor';
    			} else {
    				$classes[] = 'current-' . $queried_object->post_type . '-ancestor';
    			}
    		}

    		if ( in_array( (int) $parent_item->db_id, $active_ancestor_item_ids, true ) ) {
    			$classes[] = 'current-menu-ancestor';

    			$menu_items[ $key ]->current_item_ancestor = true;
    		}
    		if ( in_array( (int) $parent_item->db_id, $active_parent_item_ids, true ) ) {
    			$classes[] = 'current-menu-parent';

    			$menu_items[ $key ]->current_item_parent = true;
    		}
    		if ( in_array( (int) $parent_item->object_id, $active_parent_object_ids, true ) ) {
    			$classes[] = 'current-' . $active_object . '-parent';
    		}

    		if ( 'post_type' === $parent_item->type && 'page' === $parent_item->object ) {
    			// Back compat classes for pages to match wp_page_menu().
    			if ( in_array( 'current-menu-parent', $classes, true ) ) {
    				$classes[] = 'current_page_parent';
    			}
    			if ( in_array( 'current-menu-ancestor', $classes, true ) ) {
    				$classes[] = 'current_page_ancestor';
    			}
    		}

    		$menu_items[ $key ]->classes = array_unique( $classes );
    	}
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-includes/nav-menu-template.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/6.9.4/src/wp-includes/nav-menu-template.php#L327)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/6.9.4/src/wp-includes/nav-menu-template.php#L327-L605)

## 󠀁[Related](https://developer.wordpress.org/reference/functions/_wp_menu_item_classes_by_context/?output_format=md#related)󠁿

| Uses | Description | 
| [is_customize_preview()](https://developer.wordpress.org/reference/functions/is_customize_preview/)`wp-includes/theme.php` |

Whether the site is being previewed in the Customizer.

  | 
| [untrailingslashit()](https://developer.wordpress.org/reference/functions/untrailingslashit/)`wp-includes/formatting.php` |

Removes trailing forward slashes and backslashes if they exist.

  | 
| [WP_Query::get_queried_object()](https://developer.wordpress.org/reference/classes/wp_query/get_queried_object/)`wp-includes/class-wp-query.php` |

Retrieves the currently queried object.

  | 
| [is_front_page()](https://developer.wordpress.org/reference/functions/is_front_page/)`wp-includes/query.php` |

Determines whether the query is for the front page of the site.

  | 
| [is_post_type_archive()](https://developer.wordpress.org/reference/functions/is_post_type_archive/)`wp-includes/query.php` |

Determines whether the query is for an existing post type archive page.

  | 
| [_get_term_hierarchy()](https://developer.wordpress.org/reference/functions/_get_term_hierarchy/)`wp-includes/taxonomy.php` |

Retrieves children of taxonomy as term IDs.

  | 
| [wp_get_object_terms()](https://developer.wordpress.org/reference/functions/wp_get_object_terms/)`wp-includes/taxonomy.php` |

Retrieves the terms associated with the given object(s), in the supplied taxonomies.

  | 
| [get_object_taxonomies()](https://developer.wordpress.org/reference/functions/get_object_taxonomies/)`wp-includes/taxonomy.php` |

Returns the names or objects of the taxonomies which are registered for the requested object or object type, such as a post object or post type name.

  | 
| [is_taxonomy_hierarchical()](https://developer.wordpress.org/reference/functions/is_taxonomy_hierarchical/)`wp-includes/taxonomy.php` |

Determines whether the taxonomy object is hierarchical.

  | 
| [set_url_scheme()](https://developer.wordpress.org/reference/functions/set_url_scheme/)`wp-includes/link-template.php` |

Sets the scheme for a URL.

  | 
| [is_post_type_hierarchical()](https://developer.wordpress.org/reference/functions/is_post_type_hierarchical/)`wp-includes/post.php` |

Determines whether the post type is hierarchical.

  | 
| [home_url()](https://developer.wordpress.org/reference/functions/home_url/)`wp-includes/link-template.php` |

Retrieves the URL for the current site where the front end is accessible.

  | 
| [get_option()](https://developer.wordpress.org/reference/functions/get_option/)`wp-includes/option.php` |

Retrieves an option value based on an option name.

  | 
| [get_post_meta()](https://developer.wordpress.org/reference/functions/get_post_meta/)`wp-includes/post.php` |

Retrieves a post meta field for the given post ID.

  |

[Show 9 more](https://developer.wordpress.org/reference/functions/_wp_menu_item_classes_by_context/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/functions/_wp_menu_item_classes_by_context/?output_format=md#)

| Used by | Description | 
| [WP_Classic_To_Block_Menu_Converter::convert()](https://developer.wordpress.org/reference/classes/wp_classic_to_block_menu_converter/convert/)`wp-includes/class-wp-classic-to-block-menu-converter.php` |

Converts a Classic Menu to blocks.

  | 
| [wp_nav_menu()](https://developer.wordpress.org/reference/functions/wp_nav_menu/)`wp-includes/nav-menu-template.php` |

Displays a navigation menu.

  |

## 󠀁[Changelog](https://developer.wordpress.org/reference/functions/_wp_menu_item_classes_by_context/?output_format=md#changelog)󠁿

| Version | Description | 
| [3.0.0](https://developer.wordpress.org/reference/since/3.0.0/) | Introduced. |

## User Contributed Notes

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2F_wp_menu_item_classes_by_context%2F)
before being able to contribute a note or feedback.