Main content begins here

Add Image to Menu Items in Drupal 7 (D7)

Thursday, November 15, 2012

I needed to add images to a Drupal 7 menu. In my case, the menu items are pages in the site that I've added to the menu during content creation, via the Menu Settings. I wanted the menu images to be under control of the CMS (not some CSS trick) so I added a field to the Page content type to allow for an image upload I called Navigation Image.

The images are uploaded in color. Inactive menu items show black/white versions of the color image, meaning most images would be black/white most of the time. Here's how I did it.

First, make sure you've added the image upload and have uploaded a few test images. Install and enable ImageCache Actions for D7 so we can make black & white versions on the fly. Go to Configuration > Media > Image styles. Create a preset and use Desaturate to get a black and white version of whatever color image is uploaded.

In the template.php file we're going to override theme_menu_link(). Apologies, I am primarily front end so my code will not be succinct.

function THEMENAME_menu_link(array $variables) {
    // declare variables or suffer annoying warnings
    $element = $variables['element'];
    $image = '';
    $img_path = '';
    // if this menu item exists in a particular block
    if (in_array("menu_link__menu_block__2", (array) $element['#theme'])):
        // turn path into node id for this menu item
        $mnid = substr( $element['#original_link']['link_path'], 5 );
        // find original image path for this node
        $fid = db_query('SELECT field_img_nav_fid FROM {field_data_field_img_nav} WHERE entity_id = :fid', array(':fid'=>$mnid))->fetchField();
        $uri = db_query('SELECT uri FROM {file_managed} WHERE fid = :fid', array(':fid'=>$fid))->fetchField();
        // if item is NOT active use the B&W version
        if (!in_array("active-trail", (array) $element['#attributes']['class'])):
            $img_path = image_style_url('black-white', $uri);
        // if item is active use color version
            $img_path = str_replace('public:/', variable_get('file_public_path', '/sites/default/files'), $uri);
        // if we have some path insert it in image tag
            $image = '<span class="nav_image"><a href="'.url($element['#original_link']['link_path']).'"><img src="'.$img_path.'" alt="'.$element['#title'].'" /></a></span>';
    $sub_menu = '';

    if ($element['#below']) {
        $sub_menu = drupal_render($element['#below']);
    $output = l($element['#title'], $element['#href'], $element['#localized_options']);
    // if we had an image to work with, add span around original content for styling
    if($img_path): $output = '<span class="link_stuff">'.$output.'</span>'; endif;
    // add $image in front of other content so it will show as image above text
    return '<li' . drupal_attributes($element['#attributes']) . '>' . $image . $output . $sub_menu . "</li>\n";

Post new comment

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <p> <h2> <br> <img>
  • Lines and paragraphs break automatically.

More information about formatting options

This question is for testing whether you are a human visitor and to prevent automated spam submissions.

We were looking for excellent HTML skills and found them with John. If you need your HTML to look just like the mockup, he's the guy for the job.

Jason T., Lead Developer The Intelligent Investor
Copyright ©2001-2018 Way Cool Web Design LLC. All Rights Reserved.