Setting a menu item as ‘current’

We would always like to know where on the site we are on each given moment. For that, we always expect to see a special mark up for the menu item that refers to the page we’re in. To Realize such a thing, we assign a special css class (almost always containing the string ‘current’) to the said menu item, and apply special style rules to that class

As a general rule, WordPress always sees to add such a mark up to its menu items. For instance: when you’re in a certain page, the menu item that refers to this page, would always get a special ‘current’ class – probably: “current_page_item”. If your menu contains a link to a category, on the category page that the link refers to, or for each post belonging to this category, the relevant menu item will be assifned a special class – normally: ‘current-menu-item’ or ‘current-parent-item’.

However, there are times when WordPress fails to make the connection between a menu item and a post/page. For instance: you have created a special page that lists recipes from all recipe categories on your site. You call it ‘recipe main page’ and you refer to it from the ‘recipe’ menu item on the main menu. When on this page, the menu item ‘recipes’ is assigned the ‘current’ css class. But as soon as you pick an actual recipe from the list within the page and load the recipe page – even though logically you are still in the ‘recipes’ section – WordPress wouldn’t know to assign the ‘current’ class to the ‘recipes’ menu item any more.

In order to solve this – we should intercept the actual menu output and add an action to it – to always check, for instance: are we on a recipe page, and with that, are we right now handling the ‘recipe’ menu item? If so, then we should add the current class to it.

Luckily – WordPress provides us with a filter to do right that: the filter name is ‘nav_menu_css_class’ and it passes and processes the array of class for each menu item. Now we have to write a function to this filter. On each iteration on a menu item, this function checks two conditions: 1. Are we on the recipes menu item right now? 2. Is this post a recipe.

Our first task is simple: to know if we are on a certain menu item, we need to have its id. The id is very easy to indicate and be extracted from the menu items id: right click on the page to view the page source, or use Firebug to tell ‘recipes’ menu item’s id – that should be along the lines of: ‘menu-item-NN’, where NN is a number representing the actual id of this menu item. For this example let’s assume it is 42.

Our next task is a bit more complicated. We need to retrieve, not just the category id of our current post, but its root parent id, because the recipe root category may contain several sub-categories, and all should affect the ‘recipe’ menu item to get the current indication.

WordPress has a function that gets a category id and returns a string containing a breadcrumb trail of all its ancestors, all the way to its root category. The category names in this string are separated by ‘/’.

Next step is to add the extra code to handle our special current situation inside the function.php file. A reminder: this file should be located in your current them root directory. If it’s not there: simply create a file named functions.php and save it under your current theme root directory.

So first off – we write a function that retrieves the root category id from this string:

function get_root_category($category_id='') {
$ancestors = get_category_parents($category_id); //get the string containing the category ancestors
$split_arr = split("/", $ancestors); //break this string into an array
return get_cat_id($split_arr[0]); //pass the first value of this array (being the root category) to the function get_cat_id, that gets a category name, and returns its id.
}

Now we have tools to check for each page, if it is a recipe, and for each menu item being handled, if it is the ‘recipes’ menu item.

Next: we right the actual function, to be added as a filter to the menu construction:

function add_recipe_class( $classes = array(), $menu_item = false ) {
$category = get_the_category();
$category_id = $category[0] -> cat_ID;
$is_recipes = ($category_id != '' && 4 == get_root_category($category_id)); // our root recipes categories is 4. Replace 4 with your actual one
if ($is_recipes && ! in_array( 'current-menu-item', $classes ) && 42 == $menu_item->ID) { // recipes menu-item's id is 42. Replace 42 with your actual one
$classes[] = 'current-recipe'; // Off-course, the class name may be changed to anything more relevant to your case.
}
return $classes;
}

and now: adding the actual filter/ This too should be added to the function.php file:

add_filter( 'nav_menu_css_class', 'add_recipe_class', 10, 2 );

That’s it! Now, when you’re in a post belonging to the recipes root categories, you should see (viewing the page source, or using Firebug), that a new class was added to the recipes menu item: ‘current-recipe’. Now, only thing left is to apply a couple of style rules to it – and you’re good to go!