Insert an image instead of text in a menu item.

Description

To insert an image instead of text in a menu item you may rewrite theme_menu_item_link().

Step 1 of 2

Put this code into your template.php inside your themes directory:

<?php
function phptemplate_menu_item_link($item, $link_item) {
   
/* Allow HTML if the menu text is an image tag: call l() with 7th argument set to TRUE
     * See <a href="http://api.drupal.org/api/4.7/function/l
" title="http://api.drupal.org/api/4.7/function/l
" rel="nofollow">http://api.drupal.org/api/4.7/function/l
</a>     */
   
if( strpos($item['title'], '<img') === 0) {
      return
l($item['title'], $link_item['path'], !empty($item['description']) ? array('title' => $item['description']) : array(), NULL, NULL, FALSE, TRUE);
    }
   
  return
l($item['title'], $link_item['path'], !empty($item['description']) ? array('title' => $item['description']) : array());
}
?>

Here we just look for the menu title starting with the HTML tag <img and if true call l() with the 7th argument set to TRUE. This will allow HTML inside the menu text. See http://api.drupal.org/api/4.7/function/l.

Step 2 of 2

Now just enter an image tag into the "Title" field inside the "edit menu item" form (administer > menus > (edit or add item)) like <img src="/sites/default/menu_item.gif" />

Notes

  • This code should work in Drupal 5.0 too. At least the l() function did not change from 4.7 to 5.0

what about primary links?

bdornbush - February 16, 2007 - 23:47

This function works for the Navigation menu, but when I try it for a primary link item, I just see the tag as text. I would like to have images instead of text in the primary links menu in the header. Does this require rewriting another function? BTW I am using 5.1.

This seems to work

bdornbush - March 4, 2007 - 00:54

I tried the following with 5.1, and it seems to work fine.

In template.php, istead of rewriting theme_menu_item_link(),
rewrite theme_menu_links() as follows:

<?php
function phptemplate_menu_links($links) {
  if (!
count($links)) {
    return
'';
  }
 
$level_tmp = explode('-', key($links));
 
$level = $level_tmp[0];
 
$output = "<ul class=\"links-$level\">\n";
  foreach (
$links as $index => $link) {
   
$output .= '<li';
    if (
stristr($index, 'active')) {
     
$output .= ' class="active"';
    }
    if (
strpos($link['title'], '<img') === 0) {
     
$output .= ">". l($link['title'], $link['href'], $link['attributes'], $link['query'], $link['fragment'], FALSE, TRUE) ."</li>\n";
    }
    else {
       
$output .= ">". l($link['title'], $link['href'], $link['attributes'], $link['query'], $link['fragment']) ."</li>\n";
    }
  }
 
$output .= '</ul>';

  return
$output;
}
?>

Use CSS - background images

field4000 - May 29, 2008 - 01:58

You could use CSS to change the background image of each of the classes.

For example:

.links a:link, .links a:visited
{
display: block;
height: 36px;
}

.links a.menu-1-1-2
{
background: url(../../images/navigation_home.gif) no-repeat;
width: 156px;
}

.links a.menu-1-1-2:hover
{
background: url(../../images/navigation_home_over.gif) no-repeat;
}

.links a.menu-1-2-2-active
{
background: url(../../images/navigation_home_over.gif) no-repeat;
width: 156px;
}

If copying and pasting the top example

optix - July 3, 2008 - 11:57

(which works great by the way, thanks you very much), make sure you double-check the text for wrapping. This should all be on one line:

    // See <a href="http://api.drupal.org/api/4.7/function/l
" title="http://api.drupal.org/api/4.7/function/l
" rel="nofollow">http://api.drupal.org/api/4.7/function/l
</a>

ie
    // See <a href="http://api.drupal.org/api/4.7/function/l" title="http://api.drupal.org/api/4.7/function/l" rel="nofollow">http://api.drupal.org/api/4.7/function/l</a>

Otherwise you will get parse errors.

Put the image in the description field ...

ositoblanco - January 26, 2009 - 03:03

drupal-6: Put the image in the description field and exchange title and description later to show the image with the title description.

1: Change the theme_menu_item_link function in template.php to:

<?php
/**
* Implements theme_menu_item_link()
*/
function your-theme-name_menu_item_link($link) {
  if (empty(
$link['localized_options'])) {
   
$link['localized_options'] = array();
  }

  if(
strpos($link['localized_options']['attributes']['title'], '<img') === 0) {
   
// Allow HTML if the menu description is an image tag:
   
$link['localized_options']['html'] = TRUE;
   
// exchange description with title
   
$tmp = $link['localized_options']['attributes']['title'];
   
$link['localized_options']['attributes']['title'] = $link['title'];
   
$link['title'] = $tmp;
  }

  return
l($link['title'], $link['href'], $link['localized_options']);
}
?>

2: Add the image tag to the menu items description:

Enter an image tag into the "Description" field inside the "add/edit menu item" form (administer > menus > (add/edit item))
like

<img src="/sites/your-site.de/files/site/menu_image.gif" />

I'm using Drupal 6 so it was

Mr Cronk - April 20, 2009 - 22:14

I'm using Drupal 6 so it was good to see a solution for this version of Drupal.

I've adapted template.php as you suggest, then added the img tag to the description field. But still, the title text is all I see. How do I "exchange the title and description"? What exactly does that mean?

thanks!

I got this working by adding

tcom - April 24, 2009 - 10:43

I got this working by adding the <img> tag to :
Home › Administer › Site configuration › Input formats › Filtered HTML > Allowed HTML tags

I don't get this either.

Danny_Joris - May 12, 2009 - 22:58

I don't get this either. Adding < img > does not work.

Edit:
Ok it works now, but not with relative paths. Only with absolute paths. Does anyone know why?
I'm happy it works, but as the website is still in development, i will need to move it later, so it will be a bit annoying to change all those paths again.

Plus: i've got another question. Is there a way to change these pictures at onMouseOver or when a certain page is Active? If i can't make this work with drupal easily, that would be a real handicap.

If you don't want to use

ositoblanco - May 16, 2009 - 15:52

If you don't want to use javascript for this purpose the only way I know is to use css. You should give your menu item a class and set a background image for that item.class. For the class:hover you should set another background image.

In the case "when a certain page is Active" you may use the body-class. If your theme don't have this classes you need to add them. Have a look on theme documentation or for example the zen-theme. If you need more help you may ask in the drupal forum or irc.

Hey ositoblanco, thank you

Danny_Joris - May 16, 2009 - 20:13

Hey ositoblanco, thank you very much for the help. In the meanwhile i already found a perfect working sollution for this by asking the at the forum. You can find it here: http://drupal.org/node/460928

I don't get this either

pyctures - May 18, 2009 - 12:33

I added the php code in my "page.tpl.php" for bluemarine theme.
I entered an img tag in the description field for a menu item (<img src="sites/default/files/file.png" />)
I added img tag in the "allowedhtml tags"... I also tested Full HTML option...

But I just see the Menu TITLE.

Do I need to "exchange title and description" ?
How to do this ?

There is also a module for

ositoblanco - May 28, 2009 - 23:10

There is also a module for menu icons at http://drupal.org/project/menu_icons

hover image

missWilder - July 28, 2009 - 18:51

Hello ositoblanco,

Thanks for such a helpful post. I have everything working except the hover - I have a different color image in the design and need it to appear on hover but it does not... I've tried many approaches in the css, to no avail.

Any guidance is much appreciated!

To do hover IMHO you have to

ositoblanco - July 29, 2009 - 12:10

To do hover IMHO you have to use background images (or some javascript). Have you checked the above module? Otherwise you may check the drupal Forum for more Help.

Menu images with mouseover using css background-image

ositoblanco - August 4, 2009 - 00:29

Create a class name from the menu item title. Add this class name to the menu item link and wrap the link text with a span tag (to disable the display of the text title via css). In the css set for each link class the background image. This is a very easy and fast but less dynamic way (you need to change the css and upload the image when you want to change the menu item title). To fix the downside you may have a look at the Textimage module and write some custom module code.

This code goes to your themes template.php

<?php
/**
* Formats a string to be used as class name
*/
function THEMENAME_string_to_class($string) {
 
$pattern = array("ä", "ö", "ü", "ß", " ");
 
$replace = array("ae", "oe", "ue", "ss", "_");
 
// lowercase, with transformed umlauts and without all other specialchars
 
return preg_replace("%[^a-z0-9]%", "", str_replace ($pattern, $replace, strtolower(strip_tags($string))));
}

function
THEMENAME_menu_item_link($link) {
  if (empty(
$link['localized_options'])) {
   
$link['localized_options'] = array();
  }
 
  if (
$link['type'] & MENU_NORMAL_ITEM) {
   
$class = 'menu_item_THEMENAME menu_item_THEMENAME_'. THEMENAME_string_to_class($link['title']);
   
$link['title'] = '<span>'. $link['title'] .'</span>';
   
$link['localized_options']['html'] = TRUE;
   
$link['localized_options']['attributes']['class'] = empty($link['localized_options']['attributes']['class'])? $class : $link['localized_options']['attributes']['class'] .' '. $class;   
  }
 
  return
l($link['title'], $link['href'], $link['localized_options']);
}
?>

css-Example for the menu item "Example" in the menu called "Menu":

#block-menu-menu-menu .menu_item_THEMENAME span {
  display: none;
}
#block-menu-menu-menu a.menu_item_THEMENAME_example:link,
#block-menu-menu-menu a.menu_item_THEMENAME_example:visited {
  background-image: url(images/example.png);
}
#block-menu-menu-menu a.menu_item_THEMENAME_example:hover,
#block-menu-menu-menu a.menu_item_THEMENAME_example:focus,
#block-menu-menu-menu a.menu_item_THEMENAME_example:active,
#block-menu-menu-menu .active-trail a.menu_item_THEMENAME_example {
  background-image: url(images/example_hover.png);
}

NO CODE NECESSARY

Jim Leichliter - August 2, 2009 - 04:07

Using Drupal 6x:
Install menu_icons module and nice menus. When you go to edit/create your menu item, place the image tag in the Menu link title field: <img src="/sites/default/files/icons/news.png" />. Optionally you can have an image and text if you type this in the Menu link title field: <img src="/sites/default/files/icons/news.png" />News. Note the Preceding forward slash in front of "sites" for the source.

In the "Menu Icon Settings" area of the edit menu page, make sure you have the "Use an icon" checked and the path to the icon file specified WITHOUT THE PRECEDING FORWARD SLASH. Like this: sites/default/files/icons/news.png. That's it!

Jim Leichliter

I don't really get your

ksaen - August 3, 2009 - 18:24

I don't really get your advice.
For what do i need nice menus?
I tried your solution, but it didn't work. It shows <img src="/sites/default/files/icons/news.png" /> and doesn't act like a image tag.

Had the same problem - but fixed

jeffsutt - August 17, 2009 - 03:03

Had the same problem - but fixed
I had the same problem as you but figured out that jim said put a foward slash in front of sites, well that depends on how your server is configured. I removed the forward slash from both places and the image appeared.

Nice menus gives you dynamically expanding menus that you see on a lot of sites.

why isnt this in the core

jeffsutt - August 17, 2009 - 06:42

This should be in the core eh? I guess it could be part of themeing, but for a novice like me i had to check a couple different recommendations on ways of doing this which has taken a 2.5 hours and its working but still not 100% sure on mouseouts etc. Would take me 2 minutes in dreamweaver, for this basic website function.

 
 

Drupal is a registered trademark of Dries Buytaert.