DrupalDrop down menu – a smart way to present really long list of navigation links. While there have been many JavaScript based drop down menu for ages (read Dreamweaver’s mm menu), in the recent past, CSS based drop down menus have driven a more convincing point.

When it comes to Drupal, we can implement a drop down menu in your theme using the “Son of Suckerfish” CSS menu. What we are going to do is, define a region to print the suckerfish menu, have a preprocess function in the theme template file to create the appropriate link levels, add CSS and finally call it in the page.tpl.php file. Additionally, for IE, we are going to have a nifty JavaScript to fix some CSS issues. Here we go:

  • Add suckerfish region in your theme’s .info file, like, $regions[suckerfish] = Suckerfish
  • Create a new suckerfish.css file in your theme folder’s root with the following:
#primary a.active,
#secondary a.active {
  color: #CDCD8F;
}

#suckerfishmenu	.block {
  margin-bottom: 0;
  padding-bottom: 0;
}
#suckerfishmenu	.block, #suckerfishmenu	.box {
  padding: 0;
}

#suckerfishmenu	.title {
  display: none;
}

#suckerfishmenu	 {
  line-height: 28px;
  background-color:#787878;
  border-top: 1px solid #fff;
}

#suckerfishmenu	 ul.menu { /* top level ul */
  padding: 0 0 0 0px;
  list-style: none;
  z-index: 100;
  display: inline;
  float:left;
}

#suckerfishmenu	 a {
  color: #fff;
  display: block;
  padding: 0px 14px 0px 14px; /* padding between menu elements */
  margin: 0;
  text-decoration: none;
  font-size: 98%;
  font-weight: bold;
  border-right:1px solid #fff;
}

#suckerfishmenu	 a:active,
#suckerfishmenu	 a:hover {
  text-decoration: none;
  background-color:#005daa;
}

#suckerfishmenu	 li {
  display: inline;
  float: left;
  margin: 0;
  padding: 0;
  height: 1%;
}

/* second-level lists */

#suckerfishmenu	 ul.menu ul {
  padding: 0;
  margin: 0;
  list-style: none;
}

#suckerfishmenu	 ul.menu li ul {
  position: absolute;
  width: 200px;
  left: -999em; /* to hide menus because display: none isn't read by screen readers */
}

#suckerfishmenu	 ul.menu li li {
  /* height: auto; */
  float: left;
  width: 200px;
}

#suckerfishmenu	 ul.menu li li a:link,
#suckerfishmenu	 ul.menu li li a:visited {
  color: #fff;
  background: #787878;
  width: 170px;
  border: 1px solid #484848;
}

/********************************************************/
/*            ADD DOWN ARROW                            */
/*
#suckerfishmenu	 ul.menu li.expanded a {
	background: #787878 url(../images/menu_arrow_down.jpg) top right no-repeat;
	padding-right:20px;
}
#suckerfishmenu	 ul.menu li.expanded a:hover {
	background: #484848 url(../images/menu_arrow_down_h.jpg) top right no-repeat;
}
*/
/********************************************************/

#suckerfishmenu	 ul.menu li li.expanded a {
	background: #787878 url(../images/menu_arrow.png) 100% 50% no-repeat;
}

#suckerfishmenu	 ul.menu li li.expanded a:active,
#suckerfishmenu	 ul.menu li li.expanded a:hover {
	background: #005daa url(../images/menu_arrow.png) 100% 50% no-repeat;
}

#suckerfishmenu	 ul.menu li ul a:active,
#suckerfishmenu	 ul.menu li ul a:hover {
  background-color: #005daa;
  text-decoration: none;
}

#suckerfishmenu	 ul.menu li li.expanded ul.menu a {
  background: #787878;
}

#suckerfishmenu	 ul.menu li li.expanded ul.menu a:active,
#suckerfishmenu	 ul.menu li li.expanded ul.menu a:hover {
  background: #005daa;
}

#suckerfishmenu	 ul.menu li li.expanded ul.menu li.expanded a {
	background: #787878 url(../images/menu_arrow.png) 100% 50% no-repeat;
}

#suckerfishmenu	 ul.menu li li.expanded ul.menu li.expanded a:active,
#suckerfishmenu	 ul.menu li li.expanded ul.menu li.expanded a:hover {
	background: #005daa url(../images/menu_arrow.png) 100% 50% no-repeat;
}

#suckerfishmenu	 ul.menu li li {
}

#suckerfishmenu	 ul.menu li ul a {
  color: #fff;
  width: 200px;
  line-height: 26px;
  font-size: 95%;
}

#suckerfishmenu	 ul.menu li ul a:active,
#suckerfishmenu	 ul.menu li ul a:hover {
  background: #005daa;
  text-decoration: none;
}

/* margin for pullouts */
#suckerfishmenu	 ul.menu li ul ul {
  margin: -29px 0 0 200px;
}

#suckerfishmenu	 ul.menu li:hover ul ul, #suckerfishmenu ul.menu li:hover ul ul ul, #suckerfishmenu	 ul.menu li.sfhover ul ul, #suckerfishmenu	 ul.menu li.sfhover ul ul ul {
  left: -999em;
}

#suckerfishmenu	 ul.menu li:hover ul, #suckerfishmenu	 ul.menu li li:hover ul, #suckerfishmenu	 ul.menu li li li:hover ul, #suckerfishmenu	 ul.menu li.sfhover ul, #suckerfishmenu	 ul.menu li li.sfhover ul, #suckerfishmenu	 ul.menu li li li.sfhover ul {
  left: auto;
}

#suckerfishmenu	 ul.menu li ul ul ul{
  margin: -29px 0 0 200px;
}

#suckerfishmenu	 ul.menu ul li:hover ul ul, #suckerfishmenu	 ul.menu ul li:hover ul ul ul, #suckerfishmenu	 ul.menu ul li.sfhover ul ul, #suckerfishmenu	 ul.menu ul li.sfhover ul ul ul {
  left: -999em;
}

#suckerfishmenu	 ul.menu ul li:hover ul, #suckerfishmenu	 ul.menu ul li li:hover ul, #suckerfishmenu	 ul.menu ul li li li:hover ul, #suckerfishmenu	 ul.menu ul li.sfhover ul, #suckerfishmenu	 ul.menu ul li li.sfhover ul, #suckerfishmenu	 ul.menu ul li li li.sfhover ul {
  left: auto;
}

#suckerfishmenu	 ul.menu li li.expanded ul.menu li.expanded ul.menu li a { background: #787878; }
#suckerfishmenu	 ul.menu li li.expanded ul.menu li.expanded ul.menu li a:active, #suckerfishmenu ul.menu li li.expanded ul.menu li.expanded ul.menu li a:hover {
	background: #005daa;}

#suckerfishmenu	 ul.menu li li.expanded ul.menu li ul.menu li.expanded a { 	background: #787878 url(../images/menu_arrow.png) 100% 50% no-repeat; }
#suckerfishmenu	 ul.menu li li.expanded ul.menu li ul.menu li.expanded a:active, #suckerfishmenu ul.menu li li.expanded ul.menu li ul.menu li.expanded a:hover {
	background: #005daa url(../images/menu_arrow.png) 100% 50% no-repeat;}

#suckerfishmenu	 ul.menu li li.expanded ul.menu li ul.menu a {   background: #787878; }
#suckerfishmenu	 ul.menu li li.expanded ul.menu li ul.menu a:active, #suckerfishmenu ul.menu li li.expanded ul.menu li ul.menu a:hover {   background: #005daa; }

#suckerfishmenu	 ul.menu li li.expanded ul.menu li ul.menu li.expanded li ul.menu li.expanded a { background: #787878 url(../images/menu_arrow.png) 100% 50% no-repeat; }
#suckerfishmenu	 ul.menu li li.expanded ul.menu li ul.menu li.expanded li ul.menu li.expanded a:active, #suckerfishmenu ul.menu li li.expanded ul.menu li ul.menu li.expanded li ul.menu li.expanded a:hover {
	background: #005daa url(../images/menu_arrow.png) 100% 50% no-repeat;}

#suckerfishmenu	 ul.menu li li.expanded ul.menu li ul.menu li ul.menu a { background: #787878; }
#suckerfishmenu	 ul.menu li li.expanded ul.menu li ul.menu li ul.menu a:active, #suckerfishmenu ul.menu li li.expanded ul.menu li ul.menu li ul.menu a:hover {background: #005daa; }
  • Open the template.php file from your theme folder (if it does not exist, create a new template.php file in your Drupal theme folder’s root). Add the following to your template.php file (remember to change all your_theme_name to your theme name)
/* adds suckerfish.css */
drupal_add_css(drupal_get_path('theme', 'your_theme_name') . '/suckerfish.css', 'theme');

function phptemplate_menu_links($links, $attributes = array()) {

  if (!count($links)) {
    return '';
  }
  $level_tmp = explode('-', key($links));
  $level = $level_tmp[0];
  $output = "<ul class=\"links-$level ".$attributes['class']. "\" id=\"".$attributes['id']."\">\n";

  $num_links = count($links);
  $i = 1;

  foreach ($links as $index => $link) {
    $output .= '<li';

    $output .= ' class="';
    if (stristr($index, 'active')) {
      $output .= 'active';
    }
    elseif((drupal_is_front_page()) && ($link['href']=='<front>')){
      $link['attributes']['class'] = 'active';
      $output .= 'active';
    }
    if ($i == 1) {
      $output .= ' first'; }
    if ($i == $num_links) {
      $output .= ' last'; }

    $output .= '"';

    $output .= ">". l($link['title'], $link['href'], $link['attributes'], $link['query'], $link['fragment']) ."</li>\n";

    $i++;
  }
  $output .= '</ul>';
  return $output;
}
  • Open your page.tpl.php, add the following code, where ever you want the suckerfish menu to come:
<div id="suckerfish_container">
<?php if ($suckerfish): ?>
<div style="clear:both"></div>
<div id="suckerfishmenu" class="clear-block"><?php print $suckerfish; ?></div>
<?php endif; ?>
</div><!--suckerfish_container-->
  • Go to your menu administration page (admin/build/menu) and add menu items to your primary links with multiple levels. Remember to set the parent links to expanded, so that it will drop down the child links.
  • Go to your blocks page (admin/build/block) and place the primary links under the suckerfish region. If you don’t see the suckerfish region, go to admin/build/themes and enable your theme again
  • Any style / color changes can be done in the suckerfish.css file that we added earlier

IE 6 Fix

  • Create a new suckerfish.js file in your theme folder’s root and add the following code
sfHover = function() {
	var sfEls = document.getElementById("suckerfishmenu").getElementsByTagName("LI");
	for (var i=0; i<sfEls.length; i++) {
		sfEls[i].onmouseover=function() {
			this.className+=" sfhover";
		}
		sfEls[i].onmouseout=function() {
			this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
		}
	}
}
if (window.attachEvent) window.attachEvent("onload", sfHover);
  • Add the following IE specific code before the </head> in your drupal theme’s page.tpl.php
<!--[if lte IE 6]>
<script type="text/javascript" src="<?php print $GLOBALS['base_url']."/"; print $directory; ?>/suckerfish.js"></script>
<![endif]-->

Go back to your browser and enjoy your drop down menus.

While customizing the Drupal Theme for MIT – Enterprise Forum’s (India) site, I was asked to add a drop down menu. Roople Theme‘s Newsflash Drupal Theme implements the Son of Suckerfish menu for drop down. I used portions of Newsflash theme as a base for putting Suckerfish menu into my new theme. The chunks of code used in this article is taken from the Newsflash Drupal theme. Newsflash theme provides many more features, that can be set easily in the theme settings. Another popular module that I have used for drop down menus is Nice Menu module.

The Son of Suckerfish menu was earlier featured in http://www.htmldog.com/articles/suckerfish/dropdowns/.