Take the 2-minute tour ×
Drupal Answers is a question and answer site for Drupal developers and administrators. It's 100% free, no registration required.

I've cruised around the web and it is not at all obvious how to theme custom menus. I've looked for hours and have not found one single post that illustrates the process, from start to finish, of creating a menu and customizing its output. It seems like this is a multi-stage process:

  1. Create the menu through the Drupal interface.
  2. Create a theme function in your template.php file to theme the output.
  3. Expose this menu to a template file (somehow) by adding it as a variable.
  4. Call the theme function on the menu in the template file.

1 is easy enough to do, the problems I run into are with 2, 3, and 4. Looking at the default page template, I see that it exposes the main menu in the variable $main_menu. Later down the page you can see the function theme('links__system_main_menu', array('links' => $main_menu..., which means it's looking for an appropriately named theme function somewhere and using it to generate the output.

I know if I place function theme_links__system_main_menu(&$variables) {...} in my template.php file Drupal will use that function as opposed to function theme_menu_links(&$variables) {...}.

What I don't know is how Drupal links the custom menu I created with that function. Let's say for example that I created a menu called My Menu. Could I create the following function in my template.php file and theme the output for that menu? function theme_links__system_my_menu(&$variables) {...}

Also, how does one make that custom menu available to a template file? How does Drupal expose the $main_menu variable to page.tpl.php?

I think the key I'm missing here is how to embed the variable that represents my custom menu into a template page. For the most part though I'm completely lost with what to do after having created the menu.

Thanks for the help.

EDIT: Probably should post what I'm doing. Per my comment to BetaRide below, I need to inject customized HTML into the <li> elements of the menu items. Specifically, I'm adding Twitter Bootstrap icons.

share|improve this question

3 Answers 3

up vote 9 down vote accepted

Drupal's implementation of menus is a bit special, It doesn't always work the way it seems it should.

You can take a look at the core implementation of template_preprocess_page() to how the Main Menu links are added as a variable to the page template. You have to drill down a bit in the API docs, but the function you want to call in your implementation of theme_preprocess_page() is menu_navigation_links(), which will return an array of links in the menu.

Looking at line 106 of Drupal core's page.tpl.php file, you can see how the main menu links are themed in the template by calling the theme() function with a hook of 'links__system_main_menu'.

Theoretically, this implementation should be able to be duplicated with a custom menu by following the standard naming conventions. So, in template.php, you could have:

function THEMENAME_preprocess_page(&$variables){
  $variables['custom_menu'] = menu_navigation_links('menu-custom-menu');
}

function THEMENAME_links__menu_custom_menu(&$variables){
 //custom theme function here
}

and in page.tpl.php, you would add something like this:

<?php print theme('links__menu_custom_menu', array('links' => $custom_menu, 'attributes' => array('id' => 'custom-menu', 'class' => array('links', 'inline', 'clearfix')), 'heading' => t('Custom menu'))); ?>

However, adding the custom menu as a variable on your page template is not necessary. You could easily place the custom menu's block into a desired region via the Drupal admin interface. Also, you could change the site's settings for the Main Menu source, effectively replacing the default $main_menu variable in page.tpl.php with your custom menu.

EDIT: I am just seeing your addition about your end goal being to just add some custom html to the menu items for icons. Depending on how you are adding these icons, there are a couple different Drupal module options.

Menu Icons - allows you to upload an image via the Menu item's settings and automatically generates CSS (customizable via a template) that adds the image as a background on the menu item.

Menu Attributes - allows you to add a custom class to each menu item via its settings in the admin. Once a unique class is added to each menu item, you could use CSS to add an icon to the menu item or use javascript to inject the additional HTML into the menu item.

share|improve this answer
    
This seems to answer all of my questions perfectly. This is a great answer. I'll try this out immediately. –  Lester Peabody Mar 7 '12 at 17:12
1  
It worked, but I took everyone's unanimous opinion to heart and I didn't use this method. I used the Menu Attributes module that you suggested and assigned unique IDs to the specific menu items, and then used jQuery to inject the HTML directly where I needed it to be. Thanks for the tips. +1 –  Lester Peabody Mar 10 '12 at 2:31

You may want to look into nice menus - http://drupal.org/project/nice_menus.

share|improve this answer
    
I don't see why somebody voted this answer down. With Nice Menus, you can target an individual menu item since it has its own class. Then you can use a graphic as the background for that individual class. I have done it before on a couple of major projects. –  Stan Ascher Mar 7 '12 at 16:01
1  
I didn't vote it down, but I will say that this does not address the heart of the question(s) I asked, which is how to dig into the core of Drupal theming for menu items. This is why these questions never get answered fully, because there is always some module that someone name drops. I don't care about modules, I want to do template coding. –  Lester Peabody Mar 7 '12 at 16:05
1  
I didn't down vote either, but want to add to what Lester said. When you suggest a module in your answer you should also explain why you are suggesting it and how it can be used to solve the OP's issue. Without those details, your answer can be seen as not very helpful and potentially be down voted. I made that mistake on my first few answers here, too. –  sheena_d Mar 8 '12 at 0:08
    
Thanks for the feedback. –  Stan Ascher Mar 10 '12 at 20:34

Depending on what you want to customize, your approach is much to havy. Usually I create the menu through the Drupal interface as you sugested. The I take the theme developer module and Firebug to find out whicht templates, hooks and CSS directives I have to overwrite to tweak it to my needs.

It's worth considering creating a sub theme of the base theme you are using befor you start tweaking. This makes it much easier to update your base theme.

share|improve this answer
    
I need to inject customized HTML into the <li> elements of the menu items. Specifically, I'm adding Twitter Bootstrap icons. –  Lester Peabody Mar 7 '12 at 14:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.