Create CSS pin balloons with ease

April 19, 2009

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:

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>

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?

Let's discuss this on twitter.


  • ziosteve (April 19, 2009)

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

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

  • Marco (April 19, 2009)

    Pretty cute and could be really useful somewhere too.

    Just one thing: You could have used CSS 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 ;) .

  • Janko (April 19, 2009)

    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 :)

  • Davide Espertini (April 19, 2009)

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

  • mohamadreza (April 19, 2009)

    Simple and useful, Cool ;)

  • Sergejus (April 19, 2009)

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

  • Marwan (April 19, 2009)

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

  • aravind (April 19, 2009)

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

  • Janko (April 20, 2009)

    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!

  • Soh Tanaka (April 20, 2009)

    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 :-)

  • Bill Lowden (April 20, 2009)

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

  • Janko (April 21, 2009)

    Soh Tanaka: Thanks for the IE6 tip!!

    BIll: Thkx ;)

  • FreelancerCrowd (April 21, 2009)

    Nice, easy and useful.

  • Evan Byrne (April 21, 2009)

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

  • Laust Deleuran (April 21, 2009)

    [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.

  • Janko (April 21, 2009)

    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.

  • Laust Deleuran (April 21, 2009)


    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.

  • TG (April 22, 2009)

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

  • Janko (April 22, 2009)

    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 :)

  • Harry Roberts (April 22, 2009)

    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…

  • Rakesh Sharma (April 23, 2009)

    Nice Post Buddy. Thanks.

  • Craig (April 23, 2009)

    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>

  • Janko (April 26, 2009)

    Harry: UL, why not! :)

    Rakesh: thanks.

    Craig: Agree, as Soh Tanaka mentioned :)

  • RobBohn (April 27, 2009)

    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

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

  • Montana Flynn (April 28, 2009)

    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:

    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.

  • tigerP (May 5, 2009)

    非常不错.. 我喜欢

  • Webdesign Meppel (May 20, 2009)

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

  • Nicholas Z. Cardot (June 21, 2009)

    Great post. Very nice tutorial.

  • George Lucy (June 21, 2009)

    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.

  • yosry (July 4, 2009)

    its really nice post thanks

  • Helen (August 3, 2009)

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

  • Aaron (August 4, 2009)

    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.

  • Janko (August 4, 2009)

    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 :)

  • homeserve (August 4, 2009)

    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.

  • Bradford Sherrill (August 4, 2009)

    simple functionality implemented nicely

  • Young Blogger (November 7, 2009)

    Very nice tutorial will help a lot


  • archit patel (November 9, 2009)

    Its good to use…

  • Phil (November 18, 2009)

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