How to use images for menu items in Drupal with a simple preprocessing function

This tutorial is sponsored by the Save Joseph campaign, a grassroots effort to find a good friend, stellar artist and all around amazing person a satisfying, creative job in the next 8 days. I know the Drupal community could use this kind of talent. Learn more about the effort at savejoseph.org. If you have any ideas on how I can get the word out about this, let me know!

My use case was that I wanted to be able to use social media icons for menu items so that we could re-arrage, add or remove items directly from the menu management interface:. The result is what you see below:

To use images for menu items in Drupal, the first step is to create an override theme function for theme_menu_item_link() in your theme's template.php file. The idea is to first run your image handling bit to switch out text for images, and then hand it over to the parent theme to do the rest. In my case, I'm using the Zen theme.

/**
 * Implements theme_menu_item_link()
 */
function yourtheme_menu_item_link($link) {
  // Allows for images as menu items. Just supply the path to the image as the title
  if (strpos($link['title'], '.png') !== false || strpos($link['title'], '.jpg') !== false || strpos($link['title'], '.gif') !== false) {
    $link['title'] = '<img alt="'. $link['description'] .'" title="'. $link['description'] .'" src="'. url($link['title']) .'" />';
    $link['localized_options']['html'] = TRUE;
  }
  return zen_menu_item_link($link); // Let Zen take over from here.
}

Be sure to change the yourtheme in the function to the name of your theme. Also note that this only checks for .png files. If you want to use a jpeg or a gif, you will need to modify the code slightly.

Next, clear the theme registry (CTFC).

Now, you can use image paths instead of text for the image, as seen below:

Edit menu item Menu settings Path: The path this menu item links to. This can be an internal Drupal path such as node/add or page. Menu link title: sites/ ll/themes/v 1/itnages/icon-socia l-Fb png The fink text corresponding to this item that should appear in the MENU ,//www TOKEN /pagei/edit/?id= 115780915101836#!. /page to. can an OBSTREPEROUSNESS sodal- Fb DO hltp://www 115780915 10 1836#7page Tfle ESME Gallery Illustration Blog About Events Contact NASA ca Slog Abe o w iLEyents (■'-It'1, OS

Comments

You should be using theme('image') instead of writing the img HTML yourself.

I know this simply demonstrates my ignorance, but is "strpos" the name of your menu? As in your example I'll need one text menu (Gallery, Illustration, etc.) and one icon menu. Thanks!

No, "strpos" is a PHP function being used here to check if ".png" is part what the user provided for the Menu link title.

So with this example, a menu item will only render as an image if it has ".png" in the Menu link title. Otherwise it will output as a text link, like normal.

Got it working, thanks!

Good call, I made a note of this limitation in the post.

Hmmm...not quite sure what I did wrong. I placed the code inside the closing // */ of Zen's template.php, cleared the cache, ran update.php and my menu returns the path "sites/all/themes/[theme]/images/[image].png, not the image. (I know my path is correct.) Any ideas? Thanks.

Did you change "yourtheme" in the function name to the name of your theme?

BINGO! yourtheme was it. Thank You!

I've added an update to the post that mentions replacing out the *yourtheme*. Thanks!

There is a module for this.

http://drupal.org/project/spritemenu

maybe another module:
http://drupal.org/project/imagemenu ??

I'll have to give these two modules a go. I seem to remember looking briefly and deciding against them, but I can't remember why now. Maybe it was because you can't use a combination of image and textual entries? Or because you can't use the menu block module? I'll take a look and post back. Cheers!

There's a security vulnerability in your code. You are not checking whether the URL is safe before you create an img tag out of it. The URL could contain malicious JavaScript. You need to use check_url(), or better yet just use theme_image() and get some other benefits like image sizing for free.

Albeit someone who can edit menu items probably already has access to maim your site, it's still good practice to keep things secure for all situations. Sometime in the future your site may get reconfigured, or a function may get re-used by some other process, or the code may get copied and pasted somewhere else (like a public blog post), etc., etc..

P.S. The comment "Preview" button doesn't seem to work.

Ack, my bad. You are using url() which is safe. Somehow my eyes skipped right over that the first time.

Whenever I see the words "security vulnerability," I get a little PTSD. Once I crawled back out from under the table, it's good to find out it was a false start. ;)

A couple people suggested theme_image(), I'll give it a test and probably update the code above.

Cheers!

What to do with other themes (Not Zen)?

That's a good question. I think what you'd want to do is replace that last line that references the zen theme override with the following:

return theme_menu_item_link($link);

I think you mean
return theme('menu_item_link', $link);

I thought about that, but I'm pretty sure that would result in infinite recursion. So, this is the next best thing.

Good idea, though!

The method described serves good for educational & uneducational purposes ;P

You clearly show where to hack theming **BUT DO A BIG CMS NO-NO** when you obviate the right meaning of properties, attributes...

"Title" property for menu items shouldn't be utilized for another purpouse. The method has a negative SEO & usability impact since avoids setting an HTML image "title", and provides no way to set an image "alt".

A better approach would be using imagemenu module.-

what seo usability are you talking about ? that php code will never be visible by search engine, the resulting html is pure images ..

You're right about it taking over the title and alt tags, and that is unfortunate for both SEO and usability. I'll have to take a look at the imagemenu module and see if it would work the way I'd need it to.

Cheers!

how to put another image for mouse over?

Post new comment

The content of this field is kept private and will not be shown publicly.