Primary Links: "active" class for ancestors of current page and unique ID for each menu item

If you use menu.module to create your primary/secondary links, drop this php snippet into your template.php file to set an "active" class on the anchor elements for the current page and direct ancestors.

The code also gives each link a unique ID (based upon link title) that might be helpful if you are doing some CSS image replacement to spiff up your primary links.

<?php
/**
* Add frontpage 'active' state handling to menu links
* and section 'active' state handling when child is active
* and menu-[title] as css id
*
* modified from code originally posted at
* rogerlopez.net/handbook/primary_menu_tweaks
*
*/
function phptemplate_menu_item_link($item, $link_item) {
  static
$menu;
  if (!isset(
$menu)) {
   
$menu = menu_get_menu();
  }
 
$mid = $menu['path index'][$link_item['path']];
 
$front = variable_get('site_frontpage','node');
 
$attribs = isset($item['description']) ? array('title' => $item['description']) : array();
 
$attribs['id'] = 'menu-'. str_replace(' ', '-', strtolower($item['title']));
  if(((
$link_item['path']=='<front>') && ($front==$_GET['q'])) ||
    (
menu_in_active_trail($mid))){
 
$attribs['class'] = 'active';
  }
  return
l($item['title'], $link_item['path'], $attribs);
}
?>

Select the li element rather than a

<?php
function phptemplate_menu_item($mid, $children = '', $leaf = TRUE) {
 
$active_class = in_array($mid, _menu_get_active_trail()) ? ' active-trail' : '';
  return
'<li class="'. ($leaf ? 'leaf' : ($children ? 'expanded' : 'collapsed')) . $active_class .'">'. menu_item_link($mid) . $children ."</li>\n";
}
?>

Drupal 5

Note that it uses the path instead of menu item ID to determine which menu item to add the active class to.

<?php
/**
* Implementation of theme_menu_item().
*
* Add active class to current menu item links.
*/
function phptemplate_menu_item($mid, $children = '', $leaf = TRUE) {
 
$item = menu_get_item($mid); // get current menu item

  // decide whether to add the active class to this menu item
 
if ((drupal_get_normal_path($item['path']) == $_GET['q']) // if menu item path...
 
|| (drupal_is_front_page() && $item['path'] == '<front>')) { // or front page...
   
$active_class = ' active'; // set active class
 
} else { // otherwise...
   
$active_class = ''; // do nothing
 
}

  return
'<li class="'. ($leaf ? 'leaf' : ($children ? 'expanded' : 'collapsed')) . $active_class .'">'. menu_item_link($mid) . $children ."</li>\n";
}
?>

Use in Smarty

Just a note for users of the Smarty theme engine: this elegant and clean solution to the 'maintain active state for primary links'-problem also works for Smarty. Just put the above code in YOURTHEME\smartytemplate.php and change "phptemplate" to "smarty" (i.e. phptemplate_menu_item_link becomes smarty_menu_item_link).

 
 

Drupal is a registered trademark of Dries Buytaert.