Image map with CSS3 & jQuery tooltips

Tooltips can play a big role in your web designs and that isn’t new anymore. Just use them correctly and they will help you improve user experience.

We have seen before how to create some good looking CSS3 tooltips and today you’ll learn how to create an image map with pins and tooltips.

View demo

The idea

A while ago, I had to create an image map with tooltips and, being inspired by some cool tooltips I noticed on Firefox’s website, I decided to create these ones.

The principal purpose was to have something that is easy to use and update, without needing any developing knowledge.

As you will see further, you won’t need any developer skills to add pins with tooltips to an image. You’ll just need to add a div with your content and set two HTML5 custom attributes for positioning it. I’d say is simple enough.

HTML5 data attributes and jQuery

HTML5 has a cool feature named “custom data attributes”, which can help you store arbitrary snippets of metadata for the purpose of making your Javascript code simpler. So, the thing is that now you can avoid using attributes like rel or title for Javascript purposes.

Here’s how the syntax looks:

<div data-foo="bar"></div>

and this is how you can get the above value with jQuery:

var test = $('div').data('foo');

In this article, we’ll use these attributes to store data like positioning coordinates for our map pins.

Want to read more about HTML5 custom data attributes? Then check the following resources:

The HTML

<div id="wrapper">
   <img width="920" height="450" src="world-map.jpg" alt="World continents">   
   <div class="pin pin-down" data-xpos="450" data-ypos="110">	  
	  <h2>Europe</h2>	  
	  <ul>
		<li><b>Area (km²):</b> 10,180,000</li>
		<li><b>Population:</b> 731,000,000 </li>
	  </ul>
   </div>
</div>
  • #wrapper – This is the element that wraps all the other elements. Its position value is relative and I bet you guess why’s that.
  • img – the image that will behave as “background”.
  • .pin – This absolute positioned element contains the pin and also the tooltip content which will be displayed on mouseenter event. Additionally, the pin-down class specify the pin type.
  • data-xpos="450" data-ypos="110" – HTML5 custom attributes that help you specify the X (left to right) and Y (top to bottom) axis values (px) for positioning the respective map pin. In this example, the pin will be positioned 450px from left to right and 110px from top to bottom.

The CSS

There’s no much to explain here, I think the following lines are quite easy to understand:

/* Relative positioning*/
#wrapper {
	position: relative;
	margin: 50px auto 20px auto;
	border: 1px solid #fafafa;
	-moz-box-shadow: 0 3px 3px rgba(0,0,0,.5);
	-webkit-box-shadow: 0 3px 3px rgba(0,0,0,.5);
	box-shadow: 0 3px 3px rgba(0,0,0,.5);
}

/* Hide the original tooltips contents */
.pin {
	display: none;
}

/* Begin styling the tooltips and pins */
.tooltip-up, .tooltip-down {
	position: absolute;
	background: url(arrow-up-down.png);
	width: 36px;
	height: 52px;
}

.tooltip-down {
	background-position: 0 -52px;
}

.tooltip {
	display: none;
	width: 200px;
	cursor: help;
	text-shadow: 0 1px 0 #fff;
	position: absolute;
	top: 10px;
	left: 50%;
	z-index: 999;
	margin-left: -115px;
	padding:15px;
	color: #222;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	border-radius: 5px;
	-moz-box-shadow: 0 3px 0 rgba(0,0,0,.7);
	-webkit-box-shadow: 0 3px 0 rgba(0,0,0,.7);
	box-shadow: 0 3px 0 rgba(0,0,0,.7);
	background: #fff1d3;
	background: -webkit-gradient(linear, left top, left bottom, from(#fff1d3), to(#ffdb90));
	background: -webkit-linear-gradient(top, #fff1d3, #ffdb90);
	background: -moz-linear-gradient(top, #fff1d3, #ffdb90);
	background: -ms-linear-gradient(top, #fff1d3, #ffdb90);
	background: -o-linear-gradient(top, #fff1d3, #ffdb90);
	background: linear-gradient(top, #fff1d3, #ffdb90);			
}

.tooltip::after {
	content: '';
	position: absolute;
	top: -10px;
	left: 50%;
	margin-left: -10px;
	border-bottom: 10px solid #fff1d3;
	border-left: 10px solid transparent;
	border-right :10px solid transparent;
}

.tooltip-down .tooltip {
	bottom: 12px;
	top: auto;
}

.tooltip-down .tooltip::after {
	bottom: -10px;
	top: auto;
	border-bottom: 0;
	border-top: 10px solid #ffdb90;
}

.tooltip h2 {
	font: bold 1.3em 'Trebuchet MS', Tahoma, Arial;
	margin: 0 0 10px;
}

.tooltip ul {
	margin: 0;
	padding: 0;
	list-style: none;
}		

The jQuery

Below you can find the jQuery code that will execute when the page loads:

$(document).ready(function(){

    // set the wrapper width and height to match the img size
    $('#wrapper').css({'width':$('#wrapper img').width(),
                      'height':$('#wrapper img').height()
    })
    
    //tooltip direction
    var tooltipDirection;
                 
    for (i=0; i<$(".pin").length; i++)
    {				
        // set tooltip direction type - up or down             
        if ($(".pin").eq(i).hasClass('pin-down')) {
            tooltipDirection = 'tooltip-down';
        } else {
            tooltipDirection = 'tooltip-up';
            }
    
        // append the tooltip
        $("#wrapper").append("<div style='left:"+$(".pin").eq(i).data('xpos')+"px;top:"+$(".pin").eq(i).data('ypos')+"px' class='" + tooltipDirection +"'>\
                                            <div class='tooltip'>" + $(".pin").eq(i).html() + "</div>\
                                    </div>");
    }    
    
    // show/hide the tooltip
    $('.tooltip-up, .tooltip-down').mouseenter(function(){
                $(this).children('.tooltip').fadeIn(100);
            }).mouseleave(function(){
                $(this).children('.tooltip').fadeOut(100);
            })
});

View demo

How it works and how to use it

This is an example that works even on older browsers like IE6, though CSS3 features like gradients and shadows won't be available of course.

  1. Set the image (within <div id="wrapper"> element) you wish to add pins for.
  2. Add the content you need to displayed as a pin with tooltip in <div class="pin" data-xpos="450" data-ypos="110">
  3. From now on, the jQuery will do the rest:
    • Based on the image dimension, the relative wrapper inherits the img's width and height.
    • The initial content you added will be hidden (this is done via CSS) and new elements will be appended based on initial content.
    • Also, the appended pins and tooltips will be positioned using the coordinates you added as HTML5 data attributes.
    • Then, using mouseenter and mouseleave events, the tooltips are displayed/hidden.

That's all!

I hope you enjoyed this tutorial and feel free to comment if you have any suggestion. Thanks for reading!

70 thoughts on “Image map with CSS3 & jQuery tooltips

  1. Hey thanks for the article Red. Just one question… what is the benefit of defining the array inside the for loop?

    for (i=0; i<$(".pin").length; i++)
    {
    // store initial tooltips contents within an array
    var tooltipContent = new Array();
    tooltipContent[i] = $(".pin").eq(i).html();

    Isn't this preferrable?

    var tooltipContent = new Array();

    for (i=0; i<$(".pin").length; i++)
    {
    // store initial tooltips contents within an array
    tooltipContent[i] = $(".pin").eq(i).html();

    Same thing for the tooltipDirection…

    • Mat, of course, it’s not good to define an array or a variable inside a loop.

      Actually, the tooltipContent array and tooltipDirection variable aren’t used outside the loop and they are quite redundant here.

      Thanks for the heads up, when I’ll have some time I’ll update the jQuery code above.

  2. Hi Red,

    I offer my Deepest Gratitude To you for creating cool CSS3 tooltips and sharing it with us.

    I posted about you in my Gratitude Blog where I show my Gratitude To all of them for whom I’m grateful.

    And again I tweeted about your good work.

      • I am having a little hiccup with IE7′s z-index. One of my tooltip’s keeps going behind the other pins. Seems to be depend on the order of pins in my html file. Really weird.

        • Found a quick fix. Added the following css for IE7 stylesheet:

          .tooltip-up:hover {
          z-index: 1000;
          }

          .tooltip-down:hover {
          z-index: 1000;
          }

  3. Nice, but doesn’t work when you change the wrapper id. For example, if I have #wrapper already on my page (for footer push in css etc), I would have to change this id through out my site, or leave this.

    When I change the #wrapper in this tutorial to say, #map_wrapper or anything else, the whole thing breaks. Of course I also change the css and js references, but it appears you must use #wrapper in order for this to work.

    Is there a reason for this?

    Cheers :)

  4. How do I open a div which contains a set of images?
    This div should be linked in each tool tip text. like for each country i need to show some set of images.

  5. Hi Red,
    I LOVE YOU. Your efforts are really incredible and have lot of guideline for those whom don’t know more about CSS and HTML as well as other online tools you linked.
    Please tell me how I can compatible my CSS3 and HTML5 code for all browsers.
    Thanks!

    Regards,

  6. Hi Red,

    Thanks for the fantastic tooltip plugin! I have one quick question… I am trying to implement a fancybox modal overlay when users click a link that lives inside my tooltips. For some reason the modal window will not function when the link lives inside my tooltips (I have tested on the same page with links outside the tooltip and they work.) Any idea why this might be happening or thoughts on how I can get everything working?

    Thanks,
    Andrew

  7. Hi Andrew, I’m not sure…

    Just make sure you don’t have any JavaScript errors in that page. If you’re using Firebug on a Windows, hit CTRL+SHIFT+J and take a look.

    • Hey Red,

      Thanks for your response. I have tried debugging the javascrip errors on the page with no luck. I stripped all of the content out of my page except for the map with tooltips and the modal content. Below is a link to that page.

      http://karshhagan.com/testing/map_test.html

      As you can see, the modal window appears when you click the text link below the map, but not when you click the link inside of my tooltip on the map. I have tried using jsfiddle to help debug the problem but have had no luck there either. Any way you could take a look and see if you notice any glaring issues?

      Thanks again,
      Andrew

  8. Hi Red,

    This is brilliant! One question, how can I change the ‘+’ (pin before it is moused over) to show say, a country name???

    Thanks!

  9. Hi Adam, thank you and I’m glad you like it.

    Regarding your question, technically, you could to that by extracting the h2 from each, and then display it when appending the tooltip.

    I guess you know that, in this case, the pins images would need to change (increase by width), as they should be able to contain the country name for example.

    • Thanks for the reply Red,

      I understand what needs to be done but actually making it work is another thing!

      Any ideas? Forgive me I am a noob.

      The pin could simply be a div with text inside that when moused over, reveals the tooltip.

      Thanks for your help Red.

      • Adam, here’s a working example for you: http://jsfiddle.net/kdrdP/1/

        All you need to to further is to update the original “arrow-up-down.png” by increasing width and removing the “+” signs. Remove the “wheat background-color” I temporarily added.

        Hope that helps!

          • Click the following link to view my result! A touch of css and photoshop works wonders! – http://www.vapor-trail.co.uk/img_map_names/names.html

            One more question and I will finally leave you alone Red ;)…

            How would I create a different image for each location? Image dimensions will stay the same, I simply want to change the colour for each location.

            Thanks again Red you are a life saver!

          • I too am looking for a solution for this. Instead of colors, I am trying to swap the “arrow-up-down.png” file depending on location. I tried adding a div tag outside with a different id (or class) to call out a different png file. Instead, I get nothing to show but the tooltip’s popup still works.

            Example:

            .tooltip-up, .tooltip-down {
            position: absolute;
            width: 36px;
            height: 25px;
            }

            #unitedstates .tooltip-up, #unitedstates.tooltip-down {
            background: url(images/arrow-usa.png) no-repeat top left;
            }

            TEXT

  10. Thanks Red. You’re doing a wonderful service. Whether you know it or not (or even believe it) – you are serving God by providing this incredibly generous service. Bible teachers like myself are learning from you so we can make our theology websites far more effective. Thank you so much, and God bless you.

  11. Red, solution is very clear and easy to implement on our personal project. Actually we don`t use map as background. One picture taken from helicopter in birds perspective is our map of interest/dolphin tracking. Now we need to set marks for exact location where we saw dolphins and that works. We used your solution for local project in our Association and it will be recorded for presentations in our office.

    Our problem is that we try to implement popup engine to open specific link from popup content. We found http://www.pirolab.it/pirobox/ good and lightweight as solution but it seems that image is opened in new window what is wrong.

    Maybe you can help us to make it work. What part of code we need to add to your script to make it work. Or you have better solution for popup.

    Thanks in advance
    Marko

    • Hi Marko, sorry for my late reply but I’m afraid I’m not able to help you with your problem.

      To avoid wasting time by merging two different solutions , I’d recommend you to find a solution that fully fit your needs.

  12. I worked this code out to use my own map and change things to work fine for my site, but one thing I am still trying to make work is the use on ipad. The different screen sizes mess up the coordinates, but there should be a resizing addition to the code I would think, but I just can’t figure it out. Any suggestions?

  13. Just a few browser differences I found. Chrome will not automatically set the width and height of the image. If you specify the width and height ie Chrome will only pick up the width.

    Firefox will automatically detect the width and the height even without setting them on the img tag.

  14. Hi Red,

    Is there a way to vary the width of the tooltips? I have over 20 on an image and some need to be 40-50 px wider than the others so text displays correctly. Is it possible to set another class, such as “pin pin-down2″ and create a separate CSS for it? I tried to go through and add another class to the code (and was able to make one tooltip wider than the rest – so I think it might work) but then all of the tool tips went in the same direction “pin”.

    Any assistance would be great!

    Frank

  15. Hello Red,

    Thanks we are using your solution on multiple sites with great effect :)

    Just a quick question is there a way we could easily hide/show all pin points on click of a “a href”?

    Best regards

    Mat

  16. Mat, nice to hear you’re using this for your projects.

    Now, considering you’re using one of the latest jQuery versions (as 1.8.3.), you can use something like that:

    <a href="#" class="toggle-pins">Toggle map pins</a>
    
    <script>
    	(function(){
    		$('.toggle-pins').on('click', function(){
    			$('[class*="tooltip-"]').toggle();
    		})
    	})()
    </script>
    
  17. Hi guys,
    This works great! But, how do I remove the triangle that pops up during the mouse over? I want to get rid of it for my application. It’s that triangle that matches up with the background that I’m talking about when you mouse over.

  18. Hi very nice tooltip!!!!! I have just a question if i want different width for each tooltip what can I do?
    Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>