bubbletip! A jQuery Coda-style bubble tooltip plugin



Demo page





  • multiple tips on a page
  • multiple tips per jQuery element
  • tips open outward in four directions:
    • up
    • down
    • left
    • right
  • tips can be:
    • anchored to the triggering jQuery element
    • absolutely positioned
    • opened at the current mouse coordinates
    • anchored to a specified jQuery element
  • IE png transparency is handled via filters

Tested (lightly)

  • IE 6 on XP
  • IE 7 and 8 on Vista
  • Firefox 3.5 on Vista
  • Chrome 3.0 on Vista
  • Safari 3.2 on Vista


MOUSEOVER to open a tooltip above, below, to the left or to the right of any element.

MOUSEOVER a trigger element to open a tooltip above and below a target element.

Using it?

If you enjoy using it, I’d love to hear about it. Drop a comment with a link!


bubbletip was inspired by http://jqueryfordesigners.com/coda-popup-bubbles/.


    • @commarts: It is lightly tested with IE 6, 7 and 8.

      As I was testing it further, I realized that there were some issues with the AlphaImageLoader not treating the paths as relative. I made a number of changes in the css and javascript to address the performance, so please check out version 1.0.2.

  1. Awesome plugin!

    Quick question.. is is possible to make the script activation dynamic? i.e. sort of incorporating this http://www.learningjquery.com/2009/12/simple-tooltip-for-huge-number-of-elements

    I've tried the following:
    $('a.popup').live('mouseover', function() {
    $('#' + this.id).bubbletip('#' + this.id + '_popup');

    With the following html:
    <a href="#" rel="nofollow">Show me 1</a>
    <a href="#" rel="nofollow">Show me 2</a>

    <a href="#" rel="nofollow">Show me 99</a>

    <div id="1_popup">Content for 1</div>
    <div id="2_popup">Content for 2</div>

    <div id="99_popup">Content for 99</div>

    and it does work on the first mouseover, but all consecutive attempts are wonky (possibly something to do with the timeout).

    Any ideas?

  2. @Jason:

    basically, the problem is that every time you mouseover your anchor, the .bubbletip function is creating a new tip and stealing the “content” from any previously created tips…hope that makes some sense.

    so to combat that, you only want to call the .bubbletip function if the tip “content” has not already been injected into a bubbletip (i.e not a descendant of a “table.bubbletip”):

    $('a.popup').live('mouseover', function() {
        if ($('table.bubbletip #' + this.id + '_popup').length == 0) {
            $('#' + this.id).bubbletip('#' + this.id + '_popup').trigger('mouseover');

    note the .trigger('mouseover') makes the popup show the first time you mouseover. not sure if that will have issues if the bubbletip doesn't load fast enough.

    another thing to note is that there is no reuse of the bubbletip container. so if you have a thousand a.popup links on your page, you could potentially end up with a thousand bubbletip containers. i've no idea how well that would perform.

    hope that helps!

  3. Can someone tell me why this doesnt work:

    <script type="text/javascript">
    $(window).bind('load', function() {

    <div class="connect">
    <div class="email"><img src="img/connect_email.png" alt="email" id="a1_up" /><div id="tip1_up" style="display:none;"><pre class"tip1">test1</pre></div></div>
    <div class="vimeo"><img src="img/connect_vimeo.png" alt="vimeo" id="a2_up" /><div id="tip2_up" style="display:none;"><pre class"tip2">test2</pre></div></div>
    <div class="flickr"><img src="img/connect_flickr.png" alt="flickr" id="a3_up" /><div id="tip3_up" style="display:none;"><pre class"tip3">test3</pre></div></div>
    <div class="twitter"><img src="img/connect_twitter.png" alt="twitter" id="a4_up" /><div id="tip4_up" style="display:none;"><pre class"tip4">test4</pre></div></div>
    <div class="facebook"><img src="img/connect_facebook.png" alt="facebook" id="a5_up" /><div id="tip5_up" style="display:none;"><pre class"tip5">test5</pre></div></div>

    No matter how i make it its only the last div working (facebook)

    Im staring blind at it right now :(

  4. @Robert, @Vinay: Thanks!

    @Ole: I cut and paste your code and it works as expected. Could something else on the page be breaking?

  5. uhleeka, sorry i made some css positioning errors (relative/absolute) – fixed it now and it WORKS!! :o) Love your script :o)

  6. Hi,

    Is this script easily modified so that it triggers on mouse click instead of mouseover?

    I changed this row:
    $([_wrapper.get(0), this.get(0)]).mouseover(function(e) {

    to this:
    $([_wrapper.get(0), this.get(0)]).click(function(e) {

    Now it opens on mouse click, but I'd need to add a button from where to close it. Could you help me out with this?

    • @Turan:

      Basically, you need to have your close button call the "mouseout" function. So you'd need to expose a handle to that function.

      That is a bit outside of the current intention/scope of the plugin, though. So, I don't see it being something easily integrated.

  7. Thanks! Actually I got this working quite easily. As I needed both functionalites mouseover triggered and click triggered bubbletip I added one more option called triggerType with default value being 0. When value is 0 I use the normal .mouseover/.mouseout events, but when value is changed to 1 it uses .click() instead of .mouseover/.mouseout. Works like a charm!

    Thanks a lot for this script, really helped me on my project!

    One more thing. Did you know that when resizing the browser window and hovering mouse cursor over the hidden tooltip tables they come visible for some reason.

    I removed this line from the script's window resize handler and now it works properly.

    I tested on different browsers and seems like it doesn't do any harm to remove this line. Just wanted you to know!

    Once again, thanks a lot!

    • @Turan: Glad to hear you got it working! Thanks for the _wrapper.show() fix. I posted it to version 1.0.3. I also added a couple options, bindShow and bindHide, so that you can assign any events (e.g. focus and blur are good for inputs). I think that should work for your ‘click’ events as well…but I haven’t yet had a chance to test.

      latest demo is at http://www.uhleeka.com/demo/bubbletip/

      Thanks again!

  8. is it possible to get the tip content from the title attribute of the trigger? i tried this:
    <a href="#" class="windows" title="Download for XP, Vista, Win7">Download</a>
    but anchor is now invisible?!?!

  9. title = $(this).attr("title");
    this also does not work!! :(

  10. $('.apple').bubbletip($(this).attr("title"));
    with this just a empty bubble :(

  11. would it be possible to 'unbind' bubbletip functionality?
    i am not talking just hiding the tip, but dynamically removing the functionality.

    • @Michael: thanks! i added (v1.0.4) a function to remove the bubbletip. if no argument is supplied, all tips bound to the element will be removed.

      $(triggerElement).removeBubbletip([optional array of $(tips) to remove]);

  12. what a pity! please implement it in next version as a option. it makes semantically more sense than using a extra div. but sometime a div is better if you need more html tags (which are not allowed within titel attr). so both would be great! thanks in advance!

  13. Hi,
    I wonder if there is any way to delay the activation of the bubbletip – so the mouse must remain over the element for a specified time?

    There is: mouseoutDelay: 150

    I tried: mouseoverDelay: 150

    this did not work. I just want to delay the activation for a moment so the bubbletip doesn't activate immediately.

    Thanks! great plugin!

  14. Is there a way to use this with an imagemap? It would be ideal as a demonstration tool, but I've been unable to trigger it map hotspots.

    Thanks. It's the cleanest tooltip plug-in I've found!

    • @Joe: you could do something like…

      <script type="text/javascript">
      $(window).bind('load', function() {
      $('#area1').bubbletip($('#tip1'), {});
      <img usemap="#mymap" src="images/myimagemap.png" id="img1">
      <map name="mymap" id="mymap">
      <area shape="rect" coords="…" href="…" id="area1" />
      <div id="tip1" style="display:none;">this is the tip</div>

      but…i am doubtful that the position of the tip is going to work. you may have to absolutely (relative to the chosen edge of your image) position your tips–e.g.
      <script type="text/javascript">
      $(window).bind('load', function() {
      $('#area1').bubbletip($('#tip1'), { positionAtElement: $('#img1'), offsetTop: 100, offsetLeft: 100 });
      Note that the offset of 100,100 is relative to the fact that the tip is opening up (the offset 0,0 would be the center of the top edge of the image)…hope that helps!

    • @Tyler: I think it has to do with the fact that you are calling $('#tabs').tabs() potentially after you handle the tip. That function modifies the width/height of the tip contents, so the initial tip dimensions get incorrectly calculated. I'm pretty sure that you would want to call that within a $(document).ready anyhow. So try something like:

      $(document).ready(function() {

      Hope that helps.

  15. Very nice plugin. Just a quick FYI. I did a small facebook style menu at the bottom of the page on one of my websites, fixed positioning. This plugin didnt work for that and i had to modify it to recalcuate initial values on each mouseover. If the page was scrolled, the tip was appearing in the old position all the time. Thankfully it was simply a matter of calling _Calculate on each mouseover event (or whichever event is passed in the options). You need to make sure though that e.currentTarget.nodeName is not equal to TABLE.

    • @Geoff: thanks for the info. my apologies, i've done almost no testing with fixed positioning.

      alternatively, you could bind the _calculate function to the scroll event. glad to hear you got it working, though.

  16. Hi. Just found this and it seems great – tho I'm not extremely versed in jquery as yet… from Geoff's comment and your reply, how would i bind the _calculate function to calcuate initial values on each mouseover…

    i'm trying to use this with a carousel where only 3 or so entries would be visible at a time…


    • @jay: not having done any sort of testing… modify the code at line 175 to:

      var animation;
      _Calculate(); // add this line
      if (_options.positionAt.match(/^element|body$/i)) {

  17. I have a div that I'm moving to different locations on the screen. Everytime it moves, the tip needs to move with it (using CSS position: absolute and changing position with css("left", x) and css("top", y)). Think of a cartoon agent character moving to different locations of the screen explaining different controls with a tooltip.

    The first time I call agent.removeBubbletip(hint) it works fine. Then after the character moves, I call agent.bubbletip(hint) and the tip displays in a new location. But then when I call agent.removeBubbletip(hint) again the script crashes on line 344:

    $("#" + tipsActive[i][0]).get(0) is undefined
    [Break on this error] elem = $('#' + tipsActive[i][0]).get(0).parentNode;\r\n

    If I don't call removeBubbletip() I end up with stale empty tips all over the place. I tried to debug your function but didn't understand the purpose of the .data('bubbletip_tips') and why it wasn't being updated after removing tips, nor why tips were being appended to the body and hidden. I have cheated in the meantime by setting $(this).data('bubbletip_tips', null); but I'm not sure what the proper code should be :)

    • @TNP: i fixed a couple things that weren't working in the $.fn.removeBubbletip function. also, i added option.calculateOnShow (default is false); if you set it to true, it will recalculate the position of the tip just prior to making the tip visible.

      both fixes are in version 1.0.5 @ http://code.google.com/p/bubbletip/

  18. Hello there, great plugin, thanks for that. :) Tested here with IE 6/8 on Windows and Firefox 3.x on Windows/Linux. Unfortunately have some issues with Crome 4 under Linux – your demo site has some offset/padding issues ('above' bubble pops up above the link, for instance). I have implemented your code in one of my projects and it's working like charm under IE/FF, but it's not responsive with Chrome.

    • @Mario: I haven't done much testing on linux, but I do see the issue you are talking about on chrome. It doesn't always reproduce for me, though, so i am having a hard time tracking it down. One thing you might try is to set option.calculateOnShow = true.


    • @Tyler: seems to. i tested (version 1.0.5 is new as of today) on windows using IE6+, FF3.5, Safari4.0 and Chrome3.0


  19. Is it possible to make this plugin unobtrusive? Basically so I can place all my JS into an 'application.js' file instead of including <script></script> tags in my HTML. Currently, when I try this, I get an error:
    "$(tip).get(0) is undefined" from line 34.
    It would be really helpful to have that fixed. I'm looking into it and may submit a patch.

  20. Basically it looks like you just need to add:
    if ($(tip).get(0) == null) {
    return false;

    at the beginning of the "bubbletip: function(tip, options)" method.

    Maybe for a future release?

    • @Lukas: Given that this plugin requires css, IE specific css and images, I don't see how it can be set up to be any more "unobtrusive". I am open to suggestions.

      Regarding your [ if($(tip).get(0) == null) ], that should never occur. If $(tip).get(0) is null, then you have no tip. In my opinion, if you specify a tip that does not exist, the code should error, not ignore.

  21. I've been staring at the code for a good few hours and just can't work this out… The popup shows perfectly if the page width doesn't extend past 100%, but if it does, firstly it gets the position wrong (but this is corrected by setting calculateOnShow to true so not a problem) but also the popup comes up about half of the correct width, with no left/right border.

    This is on firefox, it works perfectly with IE8. Any ideas? (if what I said makes sense!)

    • @Oscar: Thanks for the feedback. I don't see an easy way to do a close button at the moment. I'll try to add that as a feature for the next release.

  22. Great work! I think I found a weird behaviour in FF3.5 for Mac. The "fade out" animation always trigged the "fade in" aniamtion if you moved the mouse just (not much) outside the mouse over area. The result was a jumping bubble.

    In a rush of hubris I took the liberty to change line 186 with a dirty fix and remove the .stop(). Why is it there? I mean the "fade out" animation should not stop at no costs. Or have I missed something?

    if (_isHiding) {
    _isActive = false;

    Again, as someone said, this is the sexiest thing on Internet ;-)

    // Jan

    • @janne: Thanks for the comments!

      The .stop(true, false) is there to stop any "hiding" animation. Basically, if the bindShow event fires during the hiding animation, we want to stop hiding, and start showing again. If you change the code as you suggest, you will not be able to show the tip until it is done hiding, i.e. you could end up over the trigger while the tip remains hidden.

      I'm not sure what is causing the "jumping bubble" effect that you are seeing (sorry i don't have a mac). Are you doing a negative offset? If you want to post your code, i'd be glad to take a look.


    • @janne: Alternatively, if you set the .delayShow to be greater than the .animationDuration, the if(_isHiding) [line 182] will always evaluate to false and thus the .stop(true,false) will never fire…I think.

    • @janne: Thanks for the screen capture. I do see the problem in FF (and conceptually in the other browsers as well).

      To prevent it, during the .bindShow event while _isHiding = true, you'd have to check and see if the current mouse coordinates are in the path of the hiding tip: if they are, then exit the .bindShow (allowing the hiding animation to complete); otherwise allow the .bindShow to complete.

      I will take a look at including it in a future release. Thanks again!

    • @gunther: are you adding the text of the tip dynamically? the plugin works by calculating the width and height during the domready event, so if you change the text after the calculation has been done, you might run into the problem you describe.

      if that is the case, you could set the option .calcuateOnShow = true to have the width/height adjusted every time the tip is shown.

      hope that helps!

  23. Hello, thank you for the great tool.
    Please have you a PSD (photoshop file) of the bubbletip? I want to modify the graphic and, if possible, I kindly ask you the file.

    Thank you

  24. Hi!
    It is possible to display a bubbletip immediately on $(document)ready ?
    I mean, without an event binding to activate the bubbletip, 'cause I need to show a bubbletip immediately after the page has been loaded…

    Also, I have a suggestion: can you use an image sprite for all the images?


    • @marcello: you could try setting the .bindShow and .bindHide to a custom event, then call a .trigger('yourCustomShowEvent') at domready.

      regarding the image sprite, (to my knowledge) IE cannot do an image sprite because of the alpha filtering. all other browsers should be loading three images at most. there are three different sprites because one has to be stretched horizontally and one vertically. if you know of a better way, i am open to suggestions.


  25. Is there a way to trigger (i.e. show) a bubbletip via a javascript function.
    Ex: something like $(triggerElement).showBubbletip()

    • @Kevin: You could set your own custom event for .bindShow and then trigger that custom event. something like:

      { bindShow : 'myCustomShowEvent' }



  26. Greetings!
    Beautiful plugin, thank you so much!

    I have implemented the plugin (1.0.5) and it works well in every browser I've tested except for IE 6,7,8 where there seems to be a padding issue with the bubbletip – the border images are exploding outward from the div. (http://www.china360online.org/confucius-learning-rites)

    I would appreciate any suggestions. Thanks in advance!


    • @daniel: Looks like you are missing the IE-only stylesheet.

      Also, i think you have declared two different versions of jQuery in your header. Not sure if that is a factor, but you probably want to fix that anyway.


  27. Hi,

    Looks beautiful. Is it possible to change the license to LGPL? There's a confusion on whether GPL can be used on a website without opening the source to the world. I want to use it on my site but can't make sure if I'll be in legal trouble.


    • @Gokhan: I have no problem changing it. I'm not sure when I am going to post the next version, though.
      @Alexis: Thanks!

  28. greetings uhleeka, thanks very much for your prompt response – I have linked the ie stylesheet. thanks again for your support and this great tool.

    all the best,

  29. Hi! Thanks very much. I really liked the script. In fact, I used it as a label on my home page (a main attraction). :)


    I'm sure to include you in my acknowledgements.

    More power!

  30. Hello uhleeka,

    Thank you for this great plugin! Excellent work!

    I have a small request. I want to style the bubble, and change it's design. I noticed the PSD bubbletip-1.0.1.psd but this is not sliced with all the .png pieces so it's very hard to create a new design. (ex. obtaining bubbletip-L-R.png slice from the .psd).

    Could you please be so kind to upload a sliced PSD with all the names mapped on the PSD slices? Thanks!!

    • @Serban: i'll see if i can do that with the next release. not sure when that will be, tho.

  31. Thanks for the amazing work! One problem i notice is when i have any extra space/formatting for example, an unordered list. i.e.:

    <pre class="tip">
    <li>list 1</li>
    <li>list 2</li>

    i get extra spaces shown in my bubble above and below each entry. i.e.:

    list 1

    list 2

    This becomes fixed if i cram everything together. i.e.:

    <pre class="tip"><ul><li>list 1</li><li>list 2</li></ul></pre>

    ie: shows correctly, no spaces as:

    list 1
    list 2

    Is there anyway I can fix this, so I can format my source code neatly? Rather than eliminate all spaces inside my div?


    • @Matt: i think that is a factor of using the <pre> tag. try using a div instead of the pre.

  32. uhleeka, first thank you for this excellent script. I first used Jquery for designs version and it worked well, except I was encountering a ton of CSS conflicts which brought me here.

    Now here I am running into some issues using the script with multiple "dynamic" elements.

    I noticed your post here: Jason on December 3rd, 2009 7:12 pm

    But it does not really help in my situation, I was hoping maybe you could take a look at the following code and provide your idea for how to solve the problem at hand.

    This is part of the code: (As you can see I changed the "a href" to a div which still works well. And below the code added the closing div. The code below places images on my site and below that is code to pull certain fields from the database to be displayed. The first tooltip works great. Unfortunately only one works)

    echo '<div id="a1_right">';

    // Image
    if( $show_listing_image ) {
    echo '<br/>';
    if ( $show_rank == 1 ) echo "&nbsp;&nbsp;&nbsp;&nbsp;";
    echo '<a href="' . $l->link . '">';
    if ($l->image_path) {
    echo '<img align="bottom" border="0" src="'. $l->image_path . '" ';
    if (($image_width !='0') AND ($image_width !='') AND ($image_height !='0') AND ($image_height !='')) echo 'width="'.$image_width.'" height="'.$image_height.'"';
    echo ' alt="' . $l->link_name . '" title="' . $l->link_name . '" />';
    } else { //if ( $show_images )
    echo '<img align="bottom" border="0" src="'.$mtconf->getjconf('live_site').$url_default_image.'" ';
    if (($image_width !='0') AND ($image_width !='') AND ($image_height !='0') AND ($image_height !='')) echo 'width="'.$image_width.'" height="'.$image_height.'"';
    echo ' alt="' . $l->link_name . '" title="' . $l->link_name . '" />';
    echo '</a>';

    echo '</div>';

    Any ideas would be helpful, keep in mind I have limited JS knowledge. More of a cut and paste, try it out kind of person.

    Demo: http://www.industrialjobs.org/development/


Comments are closed.