In particular, Jorge Mesa writes to ask how to re-create their ‘puff’ popup bubble shown when you mouse over the download image.
In essence the effect is just a simple combination of effect, but there’s a few nuances to be wary of.

How to Solve the Problem
To create the puff popup bubble effect, we need the following:
- Markup that assumes that JavaScript is disabled. It would be fair to say that the popup would be hidden from the CSS.
- The hidden popup, correctly styled for when we make it appear.
- jQuery to animate the puff effect on
mouseoverandmouseout.
The biggest trick to be wary of is: when you move the mouse over the popup, this triggers a mouseout on the image used to trigger the popup being shown. I’ll explain (carefully) how to make sure the effect doesn’t fail in this situation.
I’ve provided a screencast to walk through how create this functionality. Details on how and what I used can be found below.
Watch the coda bubble screencast (alternative flash version)
(QuickTime version is approx. 23Mb, flash version is streaming)
View the demo and source code used in the screencast
HTML Markup
For the purpose of reusability, I’ve wrapped my ‘target’ and ‘popup’ in a div. The target is the element which the user must mouseover to show the popup.
<div class="bubbleInfo">
<img class="trigger" src="http://mysite.com/path/to/image.png" />
<div class="popup">
<!-- your information content -->
</div>
</div>
CSS
There’s very little to the minimum required CSS. Of course, how you markup your bubble will change this, and the screencast uses the version from the Coda web site, so there’s a considerable amount of CSS to style the bubble.
The minimum I recommend for the example is:
.bubbleInfo {
position: relative;
}
.popup {
position: absolute;
display: none; /* keeps the popup hidden if no JS available */
}
This way we can absolutely position the popup against the trigger.
jQuery
To create the effect, we need to run the following animation on the popup element:
Mouse Over
- On
mouseover: reset the position of the popup (required because we’re floating upwards as we puff away). - Animate the popup’s opacity from 0 to 1 and move it’s CSS top position by negative 10px (to move upwards).
- If the
mouseoveris fired again, and we’re still animating - ignore. - If the
mouseoveris fired again, and the popup is already visible - ignore.
Mouse Out
- Set a timer to trigger the popup hide function (this prevents accidentally moving out of the ‘active’ area).
- If a timer is set (to hide), reset the timer (thus only allowing one hide function to fire).
- Once timed out, animiate the popup’s opacity from 1 to 0 and move it’s CSS top position by negative 10px (to float upwards away).
- Set the appropriate flags to indicate the popup is now hidden.
The ‘Trick’
There was one piece of tricky logic that initially I couldn’t work out. Each time I moved the mouse over the popup, it would fire a mouseout on the trigger element - which would hide the popup. This is an undesirable bug.
There may be a another way around this, and from what I can tell, the Coda site developers didn’t solve it this way - but here’s the solution:
You need to clear the timer set in the mouseout (point 1 above) in the mouseover. This completely solves the problem.
Complete Source Code
Here’s the complete source code for the effect, including comments throughout the code to explain what each block is doing.
$(function () {
$('.bubbleInfo').each(function () {
// options
var distance = 10;
var time = 250;
var hideDelay = 500;
var hideDelayTimer = null;
// tracker
var beingShown = false;
var shown = false;
var trigger = $('.trigger', this);
var popup = $('.popup', this).css('opacity', 0);
// set the mouseover and mouseout on both element
$([trigger.get(0), popup.get(0)]).mouseover(function () {
// stops the hide event if we move from the trigger to the popup element
if (hideDelayTimer) clearTimeout(hideDelayTimer);
// don't trigger the animation again if we're being shown, or already visible
if (beingShown || shown) {
return;
} else {
beingShown = true;
// reset position of popup box
popup.css({
top: -100,
left: -33,
display: 'block' // brings the popup back in to view
})
// (we're using chaining on the popup) now animate it's opacity and position
.animate({
top: '-=' + distance + 'px',
opacity: 1
}, time, 'swing', function() {
// once the animation is complete, set the tracker variables
beingShown = false;
shown = true;
});
}
}).mouseout(function () {
// reset the timer if we get fired again - avoids double animations
if (hideDelayTimer) clearTimeout(hideDelayTimer);
// store the timer so that it can be cleared in the mouseover if required
hideDelayTimer = setTimeout(function () {
hideDelayTimer = null;
popup.animate({
top: '-=' + distance + 'px',
opacity: 0
}, time, 'swing', function () {
// once the animate is complete, set the tracker variables
shown = false;
// hide the popup entirely after the effect (opacity alone doesn't do the job)
popup.css('display', 'none');
});
}, hideDelay);
});
});
});
Taking it Further
This effect could be perfected by changing the initial reset (popup.css()) code to read from the trigger element and approximate it’s position. In my example, I’ve hardcoded it because I only have one on the page - but you may want to use this effect several times across your page.
You should follow me on Twitter here I tweet about jQuery amongst the usual tweet-splurges!
Related screencasts
Demo
If you find this demo doesn't work as expected, it's possibly due to the demo running from within an iframe. Try running the demo in it's own window.
Source Code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>Coda Bubble Example</title>
<style type="text/css" media="screen">
<!--
* {
margin: 0;
padding: 0;
}
body {
padding: 10px;
}
h1 {
margin: 14px 0;
font-family: 'Trebuchet MS', Helvetica;
}
p {
margin: 14px 0;
font-family: 'Trebuchet MS', Helvetica;
}
.bubbleInfo {
position: relative;
top: 150px;
left: 100px;
width: 500px;
}
.trigger {
position: absolute;
}
/* Bubble pop-up */
.popup {
position: absolute;
display: none;
z-index: 50;
border-collapse: collapse;
}
.popup td.corner {
height: 15px;
width: 19px;
}
.popup td#topleft { background-image: url(http://static.jqueryfordesigners.com/demo/images/coda/bubble-1.png); }
.popup td.top { background-image: url(http://static.jqueryfordesigners.com/demo/images/coda/bubble-2.png); }
.popup td#topright { background-image: url(http://static.jqueryfordesigners.com/demo/images/coda/bubble-3.png); }
.popup td.left { background-image: url(http://static.jqueryfordesigners.com/demo/images/coda/bubble-4.png); }
.popup td.right { background-image: url(http://static.jqueryfordesigners.com/demo/images/coda/bubble-5.png); }
.popup td#bottomleft { background-image: url(http://static.jqueryfordesigners.com/demo/images/coda/bubble-6.png); }
.popup td.bottom { background-image: url(http://static.jqueryfordesigners.com/demo/images/coda/bubble-7.png); text-align: center;}
.popup td.bottom img { display: block; margin: 0 auto; }
.popup td#bottomright { background-image: url(http://static.jqueryfordesigners.com/demo/images/coda/bubble-8.png); }
.popup table.popup-contents {
font-size: 12px;
line-height: 1.2em;
background-color: #fff;
color: #666;
font-family: "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", sans-serif;
}
table.popup-contents th {
text-align: right;
text-transform: lowercase;
}
table.popup-contents td {
text-align: left;
}
tr#release-notes th {
text-align: left;
text-indent: -9999px;
background: url(http://jqueryfordesigners.com/demo/images/coda/starburst.gif) no-repeat top right;
height: 17px;
}
tr#release-notes td a {
color: #333;
}
-->
</style>
<script src="jquery.js" type="text/javascript"></script>
<script type="text/javascript">
<!--
$(function () {
$('.bubbleInfo').each(function () {
var distance = 10;
var time = 250;
var hideDelay = 500;
var hideDelayTimer = null;
var beingShown = false;
var shown = false;
var trigger = $('.trigger', this);
var info = $('.popup', this).css('opacity', 0);
$([trigger.get(0), info.get(0)]).mouseover(function () {
if (hideDelayTimer) clearTimeout(hideDelayTimer);
if (beingShown || shown) {
// don't trigger the animation again
return;
} else {
// reset position of info box
beingShown = true;
info.css({
top: -90,
left: -33,
display: 'block'
}).animate({
top: '-=' + distance + 'px',
opacity: 1
}, time, 'swing', function() {
beingShown = false;
shown = true;
});
}
return false;
}).mouseout(function () {
if (hideDelayTimer) clearTimeout(hideDelayTimer);
hideDelayTimer = setTimeout(function () {
hideDelayTimer = null;
info.animate({
top: '-=' + distance + 'px',
opacity: 0
}, time, 'swing', function () {
shown = false;
info.css('display', 'none');
});
}, hideDelay);
return false;
});
});
});
//-->
</script>
</head>
<body id="page">
<h1>Coda Bubble Example</h1>
<p>This shows a demonstration of the 'puff' popup bubble effect as seen over the download link on the <a href="http://www.panic.com/coda/">Coda web site</a>.</p>
<p>Roll the mouse over and out from the download image to see the popup fade in and out of view, while gently gliding upwards.</p>
<p><a href="http://jqueryfordesigners.com/coda-popup-bubbles">Read the article, and see the screencast this demonstration relates to</a></p>
<p><small>Note that the transparency doesn't work in IE - this is the same on the Coda web site where the images were sourced.</small></p>
<div class="bubbleInfo">
<div>
<img class="trigger" src="http://jqueryfordesigners.com/demo/images/coda/nav-download.png" id="download" />
</div>
<table id="dpop" class="popup">
<tbody><tr>
<td id="topleft" class="corner"></td>
<td class="top"></td>
<td id="topright" class="corner"></td>
</tr>
<tr>
<td class="left"></td>
<td><table class="popup-contents">
<tbody><tr>
<th>File:</th>
<td>coda 1.1.zip</td>
</tr>
<tr>
<th>Date:</th>
<td>11/30/07</td>
</tr>
<tr>
<th>Size:</th>
<td>17 MB</td>
</tr>
<tr>
<th>Req:</th>
<td>Mac OS X 10.4+</td>
</tr>
<tr id="release-notes">
<th>Read the release notes:</th>
<td><a title="Read the release notes" href="./releasenotes.html">release notes</a></td>
</tr>
</tbody></table>
</td>
<td class="right"></td>
</tr>
<tr>
<td class="corner" id="bottomleft"></td>
<td class="bottom"><img width="30" height="29" alt="popup tail" src="http://static.jqueryfordesigners.com/demo/images/coda/bubble-tail2.png"/></td>
<td id="bottomright" class="corner"></td>
</tr>
</tbody></table>
</div>
</body>
</html>

Play QuickTime version
Play Flash version

Brendan On 23rd April 2009 at 13:04
Hi all. Re my comments on August 29, 2008, I’ve since taken my blog down for redesign. If you’re interested in see an example of multiple popups, you can see one at http://www.tokyorepublik.com/popups/
Hope some of you find it useful.
Cheers.
David On 28th April 2009 at 17:04
Great tutorial.. I had a question. Lets say I have three images or triggers - how could we modify the code for the popups to contain different content depending on which image you hover on?
Matt On 30th April 2009 at 15:04
Just wondering if there’s an easy way to have the delay before the bubble is shown, something like the hoverIntent plugin. I’m using multiple bubbles on a calendar and it gets pretty intense when you roll over a bunch in a row. Thanks!
Sam On 4th May 2009 at 14:05
Hi,
I had a small question. Is it possible to use this popup bubble multiple times on the same page for different items and with different ‘content’ information for each bubble? If yes, I was hoping, you might be able to help.
Thank you.
udfd71 On 6th May 2009 at 05:05
Does anyone know how to make this ie8 compliant?
Umar On 7th May 2009 at 14:05
Must say, very good tutorial. But how to use it in wordpress??? please make full tutorial of how to install it on wordpress. Waiting for reply. :)
Regards, Umar.
Dan K. On 10th May 2009 at 04:05
I got the Coda bubble working and it looks amazing! (thank you very much for this tutorial!)… i have a question and im hoping you know that solution. I wanna use that bubble effect an a list of clients so when you scroll over each name… a bubble with their corresponding info appears. How do i code this so i can have multipple pop-up bubbles? im a noob to javascript and i tried a few things but no luck.. thats why im bugging you about this. hope it wont be a pain for you to help me. i would appreciate it very very much!
Paulo Ribeiro On 14th May 2009 at 13:05
Great tutorial! I appreciate it!
Thank you!
Продажа Электродвигателей On 14th May 2009 at 17:05
Great tutorial, but I’m coming from an AS / designer background and these long chains are super confusing - and I know I’m not the only one as I’ve seen a few critiques of this on blogs. Anyway I’m not a jQuery expert by any means but the code below makes much more sense
AJ On 18th May 2009 at 16:05
Hi!
I am using the Coda Popup bubble for a webpage I am creating. The page also contains webparts (Ajax-style drag-and-drop zones). The Coda Popup bubble works great UNTIL I move one of the webpart zones on the page. This causes some Ajaxy stuff to happen behind the scenes (without refreshing the entire page) but also seems to break the Code popup bubble from appearing until I refresh the entire page. The Coda popup bubble works great up until this point.
Does anyone have any ideas why this might be happening?
Many thanks,
AJ
Ed On 20th May 2009 at 09:05
Thanks for a great tutorial. I’ve set up a copy of this which works great, with the information for the trigger and the content being retrieved from a database. I am using AJAX to update my database and then refresh (again via AJAX) the content containing my trigger and pop-up content, but the issue I have is that when the content updates via AJAX, the pop-ups no longer appear. Do you know why this could be? A solution for this would be excellent! Thank you.
Ed On 20th May 2009 at 10:05
Is response to Dar’s comment (http://jqueryfordesigners.com/coda-popup-bubbles/comment-page-2/#comment-643), I had a similar problem and wrote a guide to the solution here: http://beatprogress.com/site.php?page=news&article=17
ganesh On 22nd May 2009 at 08:05
Frist i would thank you for creating such a wonderful thing , thanks a lot …
When i used this Coda Bubble , for testing purpose i saw thick black coloured border is coming in IE-7, is there anyway to get rid of this..?
Ремонт Электродвигателей On 24th May 2009 at 16:05
Thanks for the tutorial, single instances work great. I’d like to add my voice to the requests for a demo of it working with multiple popups on one page though, I can’t get it working with the plug in except for on the first instance of the popup.
Bim On 4th June 2009 at 10:06
Seems like a hell of a lot of code for a small little tooltip!
Guido On 6th June 2009 at 20:06
I love this tutorial because I saw this effect a few months ago and now I have a clear tutorial to create my own bubble effect. But in my opinion there’s a big trouble: this bubble effect doesn’t work in any version of IE! I’m looking at this problem now using windows vista with IE6 and IE7 on IE tester and IE8 installed. So the bubble is really cool but the effect on most used browsers is very poor. The same problem exist on Coda’s site. Is there a way to fix this problem? The effect on IE is really ugly…Thaks in advance.
CJRupak On 8th June 2009 at 14:06
That is a really nice effect! Keep up the work.
Me On 8th June 2009 at 22:06
Your transparency is not working in IE8 on PC
Joe On 9th June 2009 at 16:06
I like it, but the pop-up transparency looks terrible in IE8. Is there a fix for this?
Dennis G On 11th June 2009 at 18:06
Hi there. Did anyone has a fix for the IE PNG transparency issue? I have seen a bunch of people with code posts, but most have been taken down or do not work properly. Also, does anyone have a IE fixed version that easily allows multiple pop ups? Thanks in advance! Dennis
Dennis G On 12th June 2009 at 16:06
Just an FYI everyone. If you use the JQuery PNG Fix (google it), it fixes the IE issue and ALMOST makes this plug in cross-browser. BUT, for some reason, it removes the tail at the bottom - probably because this plug in is coded with a fixed image for the tail. If that was put in to CSS as well, I think the problem would be solved. If anyone has another fix, please let me know! Thanks, Dennis
Andy On 14th June 2009 at 16:06
First off, great tutorial. Everything works perfectly. I am only having problems with more than one popup on the same page. When I mouse over one of the triggers, both popups appear. Do you have any insight as to how to make this work with multiple popups on the same page? Thanks
Soner On 22nd June 2009 at 14:06
Fantastic !! Really !! I loved it so much. Thanx.
Danny On 23rd June 2009 at 03:06
I have a problem that every additional time I roll my mouse over the target, the popup appears higher and higher on the page. I even tried copy/pasting the example into my page, and the same problem persists.
Is there anything I should look for which could cause this issue?
Josh Martin On 25th June 2009 at 05:06
Hi,
Love the tutorial, but I was wondering if there is a way to convert this to an “onclick” window? I tried by replace onmouseover with onmousedown, but it appears then fades away immediately.
Any suggestions?