Horizontal Navigation Menus in Drupal Using CSS (Part Deux)

In our last episode, we learned how use the "float" and "display:inline" css-sledge hammers to knock drupal's nested vertical lists into displaying horizontally. Moreover we acheived this feet using three simple css rules that apply to all lists in our top-nav div to infinity. We rejoiced at the simplicity of our solution, and for a short while we believed that everything was okay in our world.

Today, the complexities of CSS will smack our rosey cheeks, burst our bubbles of optimisim, and send us hurdling back to reality. This tutorial offers nothing but blood, sweat, and tears. You will expect things to make sense -- and IE Explorer will make you look like a fool for it. However, it is a timeless truth that anything worth attaining requires sacrafice; and those who sacrafice their sanity to learning these bits of obscure knowledge will be one day kings of drupal theming, and standards based design -- they may even trick the entire drupal community into thinking they are "experts" ;-)

For those of you coming in late, this tutorial builds upon two previous articles

For the rest of you, let's begin by opening our navigation list's css file, found at themes/madness/menu.css. Say goodbye to the simple, manageable, and intelligable version of menu.css. Our task today, styling our navigation bar, will require us to make the file virtually unintelligable, unless you understand the process and theory that is used to create it.

Abandon hope, all ye who enter here

Microsoft hates jesus and America

Above, we have a screenshot of our lists as they stood at the end of our last tutorial. Can you spot the differences between firefox and explorer? Its like a magic eye poster, at first you don't see it, and then it pops out at you and say "whoa", or "dude!" (if you smoke lots of pot). If you tinkered around with CSS, than you have no doubt run into this sort of firefox vs. IE Explorer problem before. Indeed, the majority of our time in this tutorial is going to be spent figuring out ways to make our menus display consistantly in BOTH browsers. Fortunately, there is a really easy solution that works not just on this inconsistancy, but nearly 90% of the future problems you'll run into with firefox vs. explorer. Yesterday you learned how to use your CSS sledge hammers, today, you learn how to use the CSS cattle prod.

Zeroing Margins and Padding: Your CSS Cattle Prod

When browsers misbehave, always use this cattle prod as your first line of defense: "padding:0;margin:0;" Zap both #top-nav li, and #top-nav ul li ul so that menu.css looks like a so:

#top-nav li {display:inline; padding:0; margin:0;} #top-nav ul li ul {float:left; width:100%; padding:0; margin:0;} .clearnav {clear:both;}

Remember, browsers talk trash, but a quick zap with your cattle prod is usually all you need to set them straight. Here's the post "zap" proof:

I always new IE explorer was a coward

So why do we have to do this? Well, firstly, IE explorer 6 sucks(and, might I add, the sky is blue), and reads CSS differently from the agreed upon standards. So, if you ever wonder which browser's page display is "correct", it will always be firefox. If you write pages for IE explorer that do not display correctly in Firefox, than your pages will display incorrectly in all future browsers including IE explorer 7 (And, with all sincerity, I thank the IE 7 team of developers for their dedication to correcting their display model).

More specifically however, IE explorer 6 uses margins to indent its lists, where as firefox uses padding. So a safe strategy is to get in the habit of zeroing out margins and padding, and then (besides some special circumstances) using padding in most cases instead of margins. IE explorer and Firefox rarely disagree about padding, but margins are another story. Also, "be like the cool kids" and get into the habit of constantly checking your pages in both firefox and explorer.

All the professionals do it, you wanna be a dork?

And so the Plot Thinkens...

Alright time to get to the good stuff. Let's convert the top level links to simple tabs that fufill the basic requirements of any coherent navigation system. In this case, we're going to use the usability-expert's minimum requirements

  • To give the user an idea of where they are in your site
  • To give the user an idea of where they can go

Creating tabs seems straight forward enough.. a simple matter of borders, and backgrounds, but like all things we've covered there are always unforseen variables. Perhaps now is a good time to remind the reader that the goal of this tutorial is not to give a fast ready made solution, but rather to give the reader the understanding required to develop their own, and superior solutions to drupal navigation. The difference is not unlike that of giving a man a fish for a day, as opposed to teaching him to fish for a life time.

Going back to yesterday's tutorial, remember that the best way to create CSS rules is to follow your source code. So let's take a quick look at our page's source code. At first glance, this looks like an overwhelming mess. That is because you are reading it as though it is passage in a book... STOP IT! The trick is to learn how to filter through it with an eye for structure, not the actual information.

  <div id="top-nav"> <ul> <li class="collapsed"><a href="#">Anthology</a></li> <li class="collapsed"><a href="#">Culture</a></li> <li class="collapsed"><a href="#">Knowledge</a></li> <li class="collapsed"><a href="#">Media</a></li> <li class="expanded"><a href="#">Politics</a> <ul> <li class="collapsed"><a href="#">Government</a></li> <li class="expanded"><a href="#">deology</a> <ul> <li class="leaf"><a href="#">Capitalism</a></li> <li class="leaf"><a href="#">Conservatism</a></li> <li class="leaf"><a href="#">Fascism</a></li> <li class="leaf"><a href="#" class="active">Progressivism</a></li> <li class="leaf"><a href="#">Socialism</a></li> </ul> </li> <li class="collapsed"><a href="#">Politics</a></li> <li class="collapsed"><a href="#">US Foreign Policy</a></li> <li class="leaf"><a href="#">War</a></li> <li class="collapsed"><a href="#">World Affairs</a></li> </ul> </li> <li class="collapsed"><a href="#">Technology</a></li> <li class="collapsed"><a href="#">About</a></li> </ul> <br class="clearnav" /> </div>

So, we're going to be uncreative here. We will aim to create borders around the top, left, and right sides of all top level links, in addition to having contrasting backgrounds for "collapsed" links and expanded links. We are also can follow a good rule of thumb and use the same background for when a user hovers over the link as we did for a currently active, or expanding link. In addition, we do not want to apply any of the formatting for our top tabs to any other levels. Sound simple enough? I hope you laughed at that question, because our CSS file just grew over 2000 percent.

#top-nav { margin:0; padding:10px 0 0 0; }

#top-nav li { display:inline; margin:0; padding:0; }

#top-nav ul { margin:0; padding:0 0 0 10px; display:inline; }

#top-nav ul li {

}

#top-nav ul li a { border:1px #666666; border-style:solid solid none solid; font-size:14px; text-transform: uppercase; padding:2px 10px 0 10px; background-color:#eeeeee; }

#top-nav ul li a.active, #top-nav ul li a:hover, #top-nav ul li.expanded a { background-color:#FFFFFF; }

#top-nav ul li ul { float:right; width:100%; padding:0; }

#top-nav ul li ul li { background-color:#ffffff; }

#top-nav ul li ul li a { font-size:12px; text-transform:none; border:none; padding:0; }

.clearnav {clear:both;}

Take note of how rules that apply to the top level must be cancelled out on the second level, otherwise the cascade will flow through all elements. Also note that we do not apply borders and backgrounds to lines, but rather to the links themselves, and use the line classes to zero in on the various kinds of links.

Anyhow, that's all I got for today, my gymp left wrist is misbehaving, so I have to quit typing. Stay tuned for tomorrow's installment. Heh... its fun to pretend this kind of stuff has an audience larger than a cub scout pack.