![]()
In today’s excercise, we are going to adapt some nice styles to the Drupal menu items. There is a widely known CSS technique called sliding doors which became very popular since it became published. We are going to spice this a little more with extra hover states and implement sprites to improve the performance a little. This will involve a little PHP code – overriding a themeable function, and some CSS markup.
Let’s start with a piece of generated html code:
<ul class="links-menu">
<li><a href="/free">Download templates</a></li>
<li><a href="/about">About</a></li>
<li class="active"><a href="/blog" class="active">Blog</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
This is how Drupal renders primary links. Notice the active menu item which is set by a CSS class active on both the <li> and <a> tags. Since the anchor element’s parent is set to a class, it makes extremely easy to theme nice menu items.
Let’s
create a background image for the tabs. Our tab will have four states:
one for a regular item, one for hover, and both of them once they’re .active.
I prefer using sprites as this will improve performance a little:
loading several little images takes more time than loading one bigger
image which holds all the necessary background elements.
So I decided to come up with this tab image.
As
you can see, it holds all the four states and includes the right slice
and the left slice of the background. The right element applied to tag a and the left to tag li. This is very easy, but there comes IE which cripples down every great CSS idea since it can only apply hovers to element a. Now what? As we still need two different elements to be hovered, we include a span element inside every a.
Thus we need a HTML like this:
<ul class="links-menu">
<li><a href="/free"><span>Download templates</span></a></li>
<li><a href="/about"><span>About</span></a></li>
<li class="active"><a href="/blog" class="active"><span>Blog</span></a></li>
<li><a href="/contact"><span>Contact</span></a></li>
</ul>
Now we can reach the span tag via CSS using a span and a:hover span declarations. To have Drupal generate this HTML code we need to add a little function to the template.php file of your theme.
<?php
/* override item links with injecting span tags in between the link content */
function yourtheme_menu_links($links) {
if (!count($links)) {
return '';
}
$level_tmp = explode('-', key($links));
$level = $level_tmp[0];
$output = "<ul class=\"links-$level\">
";
foreach ($links as $index => $link) {
$output .= '<li';
if (stristr($index, 'active')) {
$output .= ' class="active"';
}
$output .= ">". l("<span>".$link['title']."</span>", $link['href'], $link['attributes'], $link['query'], $link['fragment'], FALSE, TRUE) ."</li>
";
}
$output .= '</ul>';
return $output;
}
?>
Of course you have to put your theme name where ‘yourtheme’ was used above. I only copied the standard function and modified the $output line a little. According to the function l we had to set the last switch to TRUE since the link text now includes HTML (the span tags).
Now let’s see the CSS code. I won’t explain fancy stuff from now on, just copy & paste my css used in Ubiquity for tabs. As we’re theming primary links, we encapsulate every style declaration in the #primary div to avoid globalizing these settings.
First, position and style the menu items:
#primary {
float: left;
margin: .75em 0 0 0;
}
#primary .links-menu {
margin: 0;
padding: 0 2em;
list-style: none;
border: 0;
}
#primary .links-menu li {
display: inline;
margin: 0;
padding: 0;
border: 0;
}
#primary .links-menu li a {
display: inline;
float: left;
margin: 0;
padding: 0 0 0 4px;
border: 0;
background: transparent url("images/tabs.png") no-repeat left top;
text-decoration: none;
}
#primary .links-menu li a span {
display: block;
background: transparent url("images/tabs.png") no-repeat right top;
padding: 5px 13px 5px 5px;
color: #039;
}
/* Commented Backslash Hack hides rule from IE5-Mac \*/
#primary .links-menu li a span { float: none; }
/* End IE5-Mac hack */
#primary .links-menu li a:hover span {
color: #006;
}
Notice the brilliant Mac IE 5 Backslash Hack which promotes IE 5 on Mac still a usable browser :)
Now here comes the part dealing with hovers and active states:
#primary .links-menu li a:hover {
background-color: transparent;
background-position: 0% -50px;
}
#primary .links-menu li a:hover span {
background-position: 100% -50px;
}
#primary .links-menu li.active a {
background-color: transparent;
background-position: 0% -100px;
}
#primary .links-menu li.active a span {
background-position: 100% -100px;
font-weight: bold;
}
#primary .links-menu li.active a:hover {
background-color: transparent;
background-position: 0% -150px;
}
#primary .links-menu li.active a:hover span {
background-position: 100% -150px;
font-weight: bold;
}
As you can see, we can do hovers with span tag inside the anchors and dealing with sprites is very easy, just tell the proper background positions in each state and you’re set to go.
Download the sample code, experiment with it, and let me know how far you went with it.