Create CSS pin balloons with ease

Home page of Africa Tour 2008, created by guys from Stylishmedia is a good example of how simple solutions can also be effective. In this tutorial I will recreate (in my own way) their effect using World map.

As I said, the effect is more than simple – each continent is marked with a "pin balloon" (I couldn't think of a better name) and when you hover the balloons they get larger. This is something that many of us have done many times, I'm sure of it. However, this example has a trick: balloons grow diagonally starting at the anchor point (anchor point is the little triangle that comes out of the balloon).

View live demo

So, we have three tasks:

  • to anchor each balloon properly
  • to position each balloon properly
  • to add the hover effect

Anchoring and positioning

Each balloon will be a div with a background image, absolutely positioned inside the relatively positioned World map. This is the HTML structure that we need.


<div id="map">
    
<div id="america"></div>
    
<div id="europe"></div>
    
<div id="africa"></div>
    
<div id="asia"></div>
    
<div id="australia"></div>
    
<div id="southAmerica"></div>
</div>

And the css:


#map { width:669px; height:351px; background-image:url('map.jpg'); position:relative;}
#map div { width: 120px; height:60px; position:absolute; cursor:pointer; background-repeat:no-repeat;}

This part is simple. Each balloon will be 120x60px, absolutely positioned.

Now, let us examine the image below. We want to anchor the balloon to the center of the North America. That is in the position x = 150px, y = 120px. Simplest way to position an element is to set its top and left values. To do that, we have to subtract the width and height of the balloon image from the x and y of the anchor point. In case of North America, our positioning point will be x = 30px, y = 60 px.

But there is more. We want our anchor point to remain fixed while the balloon grows in the opposite direction. In order to achieve this we need to position the background image properly. Div named #america will have "background-position:right bottom" and that will assure that anchor point will not move.


#america { background-image:url('america_small.png'); top:60px; left:30px; background-position:right bottom;}

This allows us to simply show another image on hover:


#america:hover {background-image:url('america_big.png');}

Let us examine the next example: Africa's balloon is flipped horizontally in comparison to North America's balloon. This only means a different background image position.

The image will be positioned to the left and bottom:


#africa{background-image:url('africa_small.png'); top:160px; left:360px; background-position:left bottom;}

Other balloons can be anchored using the same approach. Now, let's see the full CSS code:


#map { width:669px; height:351px; background-image:url('map.jpg'); position:relative;}
#map div { width: 120px; height:60px; position:absolute; cursor:pointer; background-repeat:no-repeat;}

/* Right-anchored baloons */
#america { background-image:url('america_small.png'); top:60px; left:30px; background-position:right bottom;}
#america:hover {background-image:url('america_big.png');}
#europe{background-image:url('europe_small.png'); top:50px; left:240px; background-position:right bottom;}
#europe:hover {background-image:url('europe_big.png');}
#southAmerica{background-image:url('southamerica_small.png'); top:190px; left:110px; background-position:right bottom;}
#southAmerica:hover {background-image:url('southamerica_big.png');}

/* Left-anchored baloons */
#africa{background-image:url('africa_small.png'); top:160px; left:360px; background-position:left bottom;}
#africa:hover {background-image:url('africa_big.png');}
#asia{background-image:url('asia_small.png'); top:60px; left:480px; background-position:left bottom;}
#asia:hover {background-image:url('asia_big.png');}
#australia{background-image:url('australia_small.png'); top:200px; left:540px; background-position:left bottom;}
#australia:hover {background-image:url('australia_big.png');}

As I said at the beginning, effective doesn't always mean complicated. Now, where can this effect be used? Primarily on maps (world maps, region maps or city maps). You can use it to pinpoint any location, from town to your company's headquarters, for example. I can't see any other usage, can you?

38 Responses

  1. ziosteve 19. April 2009 at 10:36

    Hello,
    excuse me but I thought that your blog is under CC.

    P.s. But why I can’t to traduce it in Italian?

  2. Marco 19. April 2009 at 10:57

    Pretty cute and could be really useful somewhere too.

    Just one thing: You could have used CSS sprites (http://www.alistapart.com/articles/sprites/) to change the background-image. The image needed to be loaded when I hovered the balloon, which took a while, showing me a short "blink".

    Another thing: You misspelled "balloon" on your example page ;) .

  3. Janko 19. April 2009 at 11:15

    ziosteve: It would be the same as if you buy a book, translate it and publish it without permission. It’s just protected by copyright.

    Marco: Sprites, of course, what was I thinking about! Ah, I always misspell something :)

  4. Davide Espertini 19. April 2009 at 15:10

    [quote]Pretty cute and could be really useful somewhere too.[/quote]
    :D

  5. mohamadreza 19. April 2009 at 15:59

    Simple and useful, Cool ;)

  6. Sergejus 19. April 2009 at 16:50

    Nice example Janko! Does :hover works on IE6? In this case we should use JS or some HTX libraries…

  7. Marwan 19. April 2009 at 17:49

    that is what makes your blog so special, always useful stuff.
    keep up the good work Janko ;)

  8. aravind 19. April 2009 at 19:34

    Pretty cool trick Janco. :)
    and I agree with Marco, you should have used sprites.

  9. Janko 20. April 2009 at 08:00

    Davide, mohamadreza, Marwan: thank you guys!

    Sergejus: I think it’s not working in IE6, some JavaScript would be needed.

    aravind: I agree with you and Marco, I totally overlooked it. Thanks for commenting!

  10. Soh Tanaka 20. April 2009 at 19:27

    Cool idea Janko~

    May I make a suggestion for the IE6 issue?

    You can use something like <a href="#" id=""></a> instead of the <div id=""></div>, this way IE6 can rely on the :hover w/out using any javascript :-)

  11. Bill Lowden 20. April 2009 at 20:15

    Nice effect. I think I’m gonna try this. Thanks!

  12. Janko 21. April 2009 at 09:49

    Soh Tanaka: Thanks for the IE6 tip!!

    BIll: Thkx ;)

  13. FreelancerCrowd 21. April 2009 at 10:35

    Nice, easy and useful.

  14. Evan Byrne 21. April 2009 at 17:30

    You should try using CSS Sprites to prevent the images from ‘jumping’ when you hover over them.

  15. Laust Deleuran 21. April 2009 at 20:08

    [b]@Marco[/b]: Yes, i was thinking about sprites right away as well – definitely the right solution for this.

    [b]@Janko[/b]; Wouldn’t it be an idea to position the inner divs according to the anchor point, so that you position #america with bottom:XXpx; right:XXpx;?
    That definitely strikes me as more logical, and it would make it possible to resize the hitarea/inner div size according to the background size.

  16. Janko 21. April 2009 at 21:29

    Evan: Of course :)

    Laust: That could be good solution if anchor points are always in the bottom-right corner. However anchor points could be placed anywhere, like in the case of Africa. It also could be positioned top-right, why not? It’s easier to calculate from a known point and that is 0,0. And the only thing that we know for sure is that top right corner of the map is 0,0 – size could vary.

  17. Laust Deleuran 21. April 2009 at 23:28

    @Janko:

    As to which corner the balloon pin’s acnhor is positioned, then the css would have to vary as well (i know this is high maintenance, but the css is pixel-based anyway, so i guess the map size won’t vary that much. If all sizes varies in relation to each other you could use percentages.)

    with africa you’d have to use bottom:XXpx;left:XXpx;, but that would still make more sense in relation to what you’re trying to achieve, at least in my mind.

    Yes it would offset everything if you decide to increase your map’s height with 10px, but if you do that, i think you’d change the maps content, and would have to reposition everything anyway, even if you use top/left consistently.

  18. TG 22. April 2009 at 06:53

    There is a delay, would you recommend prefetching the images so there is no delay on the initial hover?

  19. Janko 22. April 2009 at 08:37

    Laust: Hm, still think that having one "measurement" point is more practical and consistent. It’s easier to calculate from 0,0 for any balloon. Then you don’t have to worry where the anchor point is (if you pull images from the database, for example) but rather always position it using top:XXpx and left:XXpx.

    TG: Actually I should’ve use css sprites in this example, like Marco suggested first :)

  20. Harry Roberts 22. April 2009 at 09:55

    Nice little titbit, although surely using an unordered list would be much cleaner, as it is a menu or sorts. Apply the map as a background to the ul and each balloon being a link in a list item…

  21. Rakesh Sharma 23. April 2009 at 08:51

    Nice Post Buddy. Thanks. http://tutorialfeed.blogspot.com

  22. Craig 23. April 2009 at 13:47

    Good example.

    One thing I would change would be the divs. I would change them to links, like below then you can get the :hover effect working on IE6. No need for Java.

    <a href="#"><span style="visibility: hidden;">europe</span></a>

  23. Janko 26. April 2009 at 19:45

    Harry: UL, why not! :)

    Rakesh: thanks.

    Craig: Agree, as Soh Tanaka mentioned :)

  24. RobBohn 27. April 2009 at 18:06

    Janko – at the end of your article, you said:

    [quote]Now, where can this effect be used? Primarily on maps (world maps, region maps or city maps). You can use it to pinpoint any location, from town to your company’s headquarters, for example. I can’t see any other usage, can you? [/quote]

    Well, how about this – Let’s say you have a picture of a crowd of people, each of which needs to be identified when you hover over their face – that would be an excellent use for this type of pin balloon.

    I previously created a website a year or so ago with this requirement using a simple text popout, but always disliked the look (changing client requirements made it start out one way and end up another way). See the page at

    http://agreatdayinindy.com/Indy2008.aspx

    I think I may have to do some tweaking if I get the time!

  25. Montana Flynn 28. April 2009 at 08:59

    Thanks for the cool tut. Another way to get rid of the flicker on hover would be to load all the css images with jquery. I do this on my blog and it works great and makes the next page open faster. Here is the page with the jQuery preload plugin: http://www.filamentgroup.com/lab/update_automatically_preload_images_from_css_with_jquery/

    You can see it in action of my blog’s sidebar. The images on the twitter & delicious H2 headers is a css :hover, but because all the images are loaded with jQuery it has no flicker or delay between images.

  26. tigerP 5. May 2009 at 11:58

    非常不错.. 我喜欢

  27. Webdesign Meppel 20. May 2009 at 22:46

    Just like Marco mentioned, sprites would have made it perfect because it ‘flickers’ a bit right now. But besides that nice article!

  28. Nicholas Z. Cardot 21. June 2009 at 15:16

    Great post. Very nice tutorial.

  29. George Lucy 21. June 2009 at 17:07

    It looks really nice! Great idea! I agree, that using a sprite would be even better. And if you would like to improve it you should also preload the images.

  30. yosry 4. July 2009 at 14:10

    its really nice post thanks

  31. Helen 3. August 2009 at 19:00

    Do not use a dozen of unsemantic div! Just use a UL with list-items positioned absolutely.

  32. Aaron 4. August 2009 at 15:10

    Nice, but it would’ve been better if the image tip and rollover effect was done properly…meaning they should really be one image so there isn’t any image flicker while hovering over for the first time. Other than…pretty cool.

  33. Janko 4. August 2009 at 15:24

    Thanks everyone!

    RobBohn: Nice idea!

    Montana Flynn, Aaron, George Lucy: Totally agree, it should be done, preferably with css sprites.

    Helen: At first I was thinking to do it using UL, but I gave up. Can’t explain why :)

  34. homeserve 4. August 2009 at 17:27

    I agree with the comments on the slight flicker the first time that the balloon is hovered over … but the part I like the most is a simple one – the balloon can expand top right or to top left according to how you set it up and the requirements for the position of the marker.

    As you said "effective doesn’t always mean complicated" and in this instance a small additional thought makes the visual impression more effective.

    Only downside – looks to take a long time to implement.

  35. Bradford Sherrill 4. August 2009 at 17:43

    simple functionality implemented nicely

  36. Young Blogger 7. November 2009 at 23:40

    Very nice tutorial will help a lot

    Thanks,

  37. archit patel 9. November 2009 at 10:09

    Its good to use…

  38. Phil 18. November 2009 at 16:30

    Should check for some pre-load options aswell, the first time you hover it kinda feels buggy.
    Nice stuff tho.