Styling Menus in Drupal

I’m warming to the Drupal content management framework (as we’re apparently meant to call it). For getting a site up and running in record time, you really can’t beat it. Well, OK, maybe you can beat it with Rails, but I wouldn’t necessarily wager a lot on that. (I haven’t done, and don’t know anyone who’s done, a side-by-side comparison using people of roughly equal proficiency in both frameworks, and I really don’t have a guess as to how it would come out.) But it has a massively steep learning curve, and even once you’re getting the hang of things, it can still be really frustrating making it do exactly what you want.

Case in point – I’m making a new site for the Indiana University Swahili STARTALK summer program, and I would like to have my internal menus be styled without those annoying list dots. Is that so much to ask?

Yes. Yes it is.

Now, in Rails (or comparable write-it-yourself framework) this would be a piece of cake. Assuming I was even implementing the navigation menu as a list (which I probably would’t be, actually) in the first place, I’d just go to the partial view file, slap a class on the ul wrapper that contained the spec list-style-type: none, and DONE.

In Drupal it’s a little more … ahem … complicated. Drupal ships with a “Menu” content type, and for making menus you’re supposed to use that. The advantage to doing so is that your client users, who know nothing about web programming, can just log in as administrator and add a link themselves without having to bug you to do it for them. The DISadvantage is that Drupal has already made up its own mind about how these things are structured and styled. Specifically, it makes you an unordered list, and each list item gets the class leaf, which apparently entails it having the default list-style-type. Annoying.

Now, to give Drupal its due, it does give me a pre-fab menu type, which other systems don’t. No matter what system I’m in, I have to style these things myself to get them the way I want them to look, so what’s the big deal?

The big deal, of course, is figuring out what to override to restyle the menu. Since the culprit leaf class is baked right there into the individual li elements, there’s really no choice but to use a theme template override.

So, I made a template.php file, put it in sites/all/themes/mytheme/, and added the following code:

function mytheme_menu_link(array $variables) {
  $element = $variables['element'];

  if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  }
  $output = l($element['#title'], $element['#href'], $element['#localized_options']);
  foreach($element['#attributes']['class'] as $k => $v){
    if($v == 'leaf'){
      unset($element['#attributes']['class']);
    }
  }
  return '' . $output . $sub_menu . "n";
}

That’s a simple copy-n-paste from the theme_menu_link theme hook spec, just adding the bit about removing the leaf class if it’s there.

And that’s “all” it takes. Relatively painless, right? Right, BUT… well, you can see why things like this put people off of Drupal. For one thing, it’s kind of a black art figuring out that there’s an override themeing hook for menu items, and then locating it. For another thing, there’s just something a little ugly about having the system generate an entire syntax tree for a menu, and then, once that’s done, having the program go back in and transform that tree to get output. In most frameworks, you’d just write the menu yourself, and there’d be no need for it to pass through all these modification layers before showing up on the page. So, this is classic Drupal in all its ugliness. Serious “elegance FAIL.”

But the upshot is that once you really get the hang of all this stuff, you can churn out user-configurable websites in no time for fun and profit, so I’m not complaining. In fact, I’m toying with the idea of rewriting Drupal in Python as a nice exercise in learning Drupal. Because there are certainly worse things to be an expert in.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>