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.
You're the bomb John.
Y. G. D.
Copyright ©2001-2018 Way Cool Web Design LLC. All Rights Reserved.