Build a Better Tooltip with jQuery Awesomeness

Build a Better Tooltip with jQuery Awesomeness

Tutorial Details
  • Technology: jQuery
  • Difficulty: Intermediate
  • Completion Time: 1-2 hours

Browsers will automatically display a tooltip when you provide a title attribute. Internet Explorer will also use the alt attribute. But, in this tutorial I’m going to show you how to quickly write a jQuery plugin that will replace the typical browser tooltip with something a little flashier.

One of the great tools we have in our web development goodie-bag are tooltips. A tooltip is a box
that appears when you hover your cursor over an element like a hyperlink. It provides supplementary
information about that element. For example, a link with little or no text (an icon) may become confusing.
Provide an extra sentence or two within a tooltip to explain to your users what will happen if they click on it.


Before You Start

This tutorial would probably fit in the category of Intermediate. The instructions assume that you have at least
a basic understanding of HTML/CSS, slicing techniques and jQuery.

If you need a refresher on jQuery, here are a few recommended sites:

Just so you have a clear idea of the files involved in this tutorial, here is what the file structure should look
like by the time you are done.

The file structure

Here’s a rundown of what each file/folder is:

  • Images folder contains the following images:
  • – - tipTip.png – created in Step 2
  • – - tipMid.png – created in Step 2
  • – - tipBtm.png – created in Step 2
  • index.html – – created in Step 3
  • style.css – created in Step 3
  • jquery-1.3.1.min.js – download this here
  • jquery.betterTooltip.js – – created in Step 5

Step 1 - First, Get a Little Creative

Open up Photoshop, or your software of choice, and whip up an awesome looking tooltip. Rather than designing
on a plain white background, it may help to draw up your tooltip on a background similar to that of your site.
That way it will blend in seamlessly. For the most part, there is no right or wrong way
to complete this step. Just use your imagination and creativity.

Initial Tooltip Design

Step 2 - Slice and Dice Your Tooltip

For this particular design, you will need to slice the tooltip into 3 different images. This particular design will need a PNG to preserve transparency.
1) The top piece. 2) A thin 1 pixel slice that will repeat vertically in the middle. 3) The bottom piece. The 4th part of the diagram below shows the three
pieces after they were cut out.

Place these image files into a folder named “images”.

Slice up the tooltip

Note: Internet Explorer does NOT like PNG transparency. Even IE 7 only partially supports it. If you animate a
PNG with JavaScript, any area with transparency will turn black momentarily while in movement. I’m using this design
knowing full well it will have issues in IE that are hard to work around.


Step 3 - Write the HTML/CSS Markup

With the images sliced, we can move on to the HTML and CSS markup. This will be the easiest part of the whole
tutorial.

The HTML

This HTML markup will soon be moved into an external JavaScript file, so just type this in whatever
is most convenient and can be referred to later.

	<div class="tip">
		<div class="tipMid"></div>
		<div class="tipBtm"></div>
	</div>

There are three div tags. Two nested inside a parent. The first div, “tip” will be used to hold everything together
and display the top portion of the tooltip, tipTop.png.

“tipMid” will eventually hold the text that the tooltip will display. It will also have tipMid.png repeating vertically inside it.

“tipBtm” is solely there to display the bottom portion of the tooltip, tipBtm.png.

Inside of index.html, add a bunch of filler text and some elements with their title attributes filled out. Such as:

	This is a link

In the head of index.html, you will need to link to the stylesheet and the two JavaScript files.

	<link href="style.css" rel="stylesheet" type="text/css" media="all" />
	<script type="text/javascript" src="jquery-1.3.1.min.js"></script>
	<script type="text/javascript" src="jquery.betterTooltip.js"></script>

The CSS

The CSS used for this tooltip is relatively simple, just add the following to style.css

	.tip {
		width: 212px;
		padding-top: 37px;
		display: none;
		position: absolute;
		background: transparent url(images/tipTop.png) no-repeat top;}

	.tipMid {background: transparent url(images/tipMid.png) repeat-y; padding: 0 25px 20px 25px;}
	.tipBtm {background: transparent url(images/tipBtm.png) no-repeat bottom; height: 32px;}

Let me explain the above.

The wrapping element, .tip, is used to hold everything together. It has a top padding of 37 pixels.
That’s the height of the image in the background. The padding will push the child elements down to reveal
the image behind. It also has a position absolute so that we can move it around on top of the page
content.

The other two classes simply have a background image and, in the case of .topMid, padding to give the
content that will be placed inside, some room to breathe.


Step 4 - Why a Plugin?

jQuery is pretty cool by itself. But the real magic is in extending it with a plugin. When you put your
code into a plugin, you are making it reusable. That way you can build up a code library and never write
the same code twice.

Here is the tooltip plugin in its entirety:

	$.fn.betterTooltip = function(options){

		/* Setup the options for the tooltip that can be
		   accessed from outside the plugin              */
		var defaults = {
			speed: 200,
			delay: 300
		};

		var options = $.extend(defaults, options);

		/* Create a function that builds the tooltip
		   markup. Then, prepend the tooltip to the body */
		getTip = function() {
			var tTip =
			"<div class='tip'>" +
				"<div class='tipMid'>"	+
				"</div>" +
				"<div class='tipBtm'></div>" +
			"</div>";
			return tTip;
		}
		$("body").prepend(getTip());

		/* Give each item with the class associated with
		   the plugin the ability to call the tooltip    */
		$(this).each(function(){

			var $this = $(this);
			var tip = $('.tip');
			var tipInner = $('.tip .tipMid');

			var tTitle = (this.title);
			this.title = "";

			var offset = $(this).offset();
			var tLeft = offset.left;
			var tTop = offset.top;
			var tWidth = $this.width();
			var tHeight = $this.height();

			/* Mouse over and out functions*/
			$this.hover(function() {
				tipInner.html(tTitle);
				setTip(tTop, tLeft);
				setTimer();
			},
			function() {
				stopTimer();
				tip.hide();
			}
		);		   

		/* Delay the fade-in animation of the tooltip */
		setTimer = function() {
			$this.showTipTimer = setInterval("showTip()", defaults.delay);
		}

		stopTimer = function() {
			clearInterval($this.showTipTimer);
		}

		/* Position the tooltip relative to the class
		   associated with the tooltip                */
		setTip = function(top, left){
			var topOffset = tip.height();
			var xTip = (left-30)+"px";
			var yTip = (top-topOffset-60)+"px";
			tip.css({'top' : yTip, 'left' : xTip});
		}

		/* This function stops the timer and creates the
		   fade-in animation                          */
		showTip = function(){
			stopTimer();
			tip.animate({"top": "+=20px", "opacity": "toggle"}, defaults.speed);
		}
	});
};

Step 5 - Write the Plugin

Now that you’ve seen what the code looks like, it’s time to dissect it.
To get started, create a .js file and name it jquery.betterTooltip.js to make it compliant with jQuery
plugin standards.

Inside that .js file, include the following code:

	$.fn.betterTooltip = function(){

	});

This creates a public function that can be invoked from the head of a document or
another external .js file. To invoke your plugin, you need to call the follow line from within a
$(document).ready page event.

	$(document).ready(function(){
		$('.tTip').betterTooltip();
	});

The above line will attach the plugin to every element with the class name of “tTip”. Likewise, you
could attach it to any element of your choosing.

Expose the Plugin Settings

In order to prevent having to modify the plugin for every project it’s important to expose some of the
variables and settings so they can be tweaked from outside the plugin itself. The ultimate goal would be
to never touch the plugin, just adjust its settings. To do this, add the following to that first chunk
of code:

	$.fn.betterTooltip = function(options){
		/* Setup the options for the tooltip that can be
		   accessed from outside                      */

		var defaults = {
			speed: 200,
			delay: 300
		};

		var options = $.extend(defaults, options);
	});

This allows the settings “speed” and “delay” to be modified when the plugin is invoked like this:

	$('.tTip').betterTooltip({speed: 600, delay: 600});

These are completely optional. If not specified, the plugin will use the default values.

Inject the Tooltip Markup

Remember that HTML you typed up for the tooltip? It will now make its official appearance.
In this chunck of code, the jQuery “prepend” content manipulation is used to inject the tooltip
immediately after the opening body tag. This way we can make sure that the tooltip
is positioned on top of everything.

	/* Create a function that builds the tooltip
	   markup. Then, prepend the tooltip to the body */
	getTip = function() {
		var tTip =
		"<div class='tip'>" +
			"<div class='tipMid'>"	+
			"</div>" +
			"<div class='tipBtm'></div>" +
		"</div>";
		return tTip;
	}
	$("body").prepend(getTip());

The $(this).each function

This is one of the most important and useful aspects of a jQuery plugin. The $(this).each function
loops through each page element that is associated with the plugin when it was evoked. In this case it’s
all elements with the “tTip” class. When it loops through each element it applies the properties and methods
that you specify.

	$(this).each(function(){

		var $this = $(this);
		var tip = $('.tip');
		var tipInner = $('.tip .tipMid');

		var tTitle = (this.title);
		this.title = "";

		var offset = $(this).offset();
		var tLeft = offset.left;
		var tTop = offset.top;
		var tWidth = $this.width();
		var tHeight = $this.height();

		/* Mouse over and out functions*/
		$this.hover(function() {
			tipInner.html(tTitle);
			setTip(tTop, tLeft);
			setTimer();
		},
		function() {
			stopTimer();
			tip.hide();
		}
	);

This is fairly simple. The top half consists of a bunch of properties for the height, width, x & y position and
even the title attribute value of the “tTip” elements. I’m using the jQuery offset() CSS method to grab the top and left position. There is also a
hover function assigned to each “tTip” class that calls methods on mouse over and out. These methods will be described
further down in the tutorial.

One important part of the $(this).each function is this line of code here that removes the title attribute:

	this.title = "";

The whole point of this tooltip is to swap the generic
tooltip with a better eye catching version. If you don’t remove the title attribute, which the browser
uses to generate the generic tooltip, you will get duel tooltips. Like this:

Avoid duel tooltips

Delay the Fade-in Animation of the Tooltip

		/* Delay the fade-in animation of the tooltip */
		setTimer = function() {
			$this.showTipTimer = setInterval("showTip()", defaults.delay);
		}

		stopTimer = function() {
			clearInterval($this.showTipTimer);
		}

These two methods, setTimer and stopTimer are used to create a delay from when the user hovers
their cursor over the element with the “tTip” class and when the tooltip makes its appearance. This
is important to avoid annoying users. I’m sure we all share the frustration when we accidentally hover
over one of those pop-up ads that are hidden in the content of sites.

The setTimer method creates a setInterval object that calls “showTip()” after the allotted time has passed.
In order for setInterval to not loop infinitely, the method stopTimer is called to stop the setInterval object.

Position the Tooltip

		/* Position the tooltip relative to the class
		   associated with the tooltip                */
		setTip = function(top, left){
			var topOffset = tip.height();
			var xTip = (left-30)+"px";
			var yTip = (top-topOffset-60)+"px";
			tip.css({'top' : yTip, 'left' : xTip});
		}

The hover function inside the $(this).each loop, that was created earlier, calls setTip(). Its purpose is to position
the tooltip directly above “tTip” element. This is done prior to the fade-in animation.

Tooltip Fade-in Animation

		/* This function stops the timer and creates the
		   fade-in animation                          */
		showTip = function(){
			stopTimer();
			tip.animate({"top": "+=20px", "opacity": "toggle"}, defaults.speed);
		}
	});
};

Last but not least, the showTip() function. This uses jQuery’s animate() UI effect to fade the tooltip in
while simultaneously sliding it down.


Wrapping it Up. . .

Once you are done and happy with your results, you can move your plugin from the basic HTML page full of filler text to
the real world and put it to use.

This is a very basic example of what a tooltip plugin can do. The fun part now will be to make it more robust.
There are all sorts of ways to expand this plugin. A needed enhancement would be detecting
the location of the tooltip in relation to the boundaries of the browser window and displaying the tooltip accordingly so
it doesn’t get cut off.

Thanks for reading this tutorial. I hope it shed some light on how you can use jQuery to enhance your website’s
interface.

Let the comments begin! I want to hear what you think. Does this technique actually help users get around easier,
or is it just another annoyance?

  • Subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.


Add Comment

Discussion 156 Comments

Comment Page 2 of 3 1 2 3
  1. Khro says:

    Very nice! (a good example of using PNG as well)

  2. plisvb says:

    Tooltip is completely off in safari on the mac, firefox is fine, ie8 is ok but there’s a little black flash of the transparent part of the images before it corrects itself. Would be interested if an update happened too.

    Good job

  3. AlfredN says:

    Nice one with the plugin; thanks guys.

  4. Keay says:

    Great work….Jquery is always cool!!

  5. nurettin says:

    i like it. this script very good

  6. Another awesome plugin. very easy to customize.
    for ie6, you will need to use pngfix script

    K.

  7. At first I was really excited about this tooltip-plugin (and it is still pretty awesome), but unfortunately there is not much use for this plugin right now, especially with the fixed window-size. Therefore it would be great to see this project develop. I’m sure many people can learn a lot from this :)

    All the best!
    Sebastian

  8. vivek kr. singh says:

    Thanks ,
    Very usefull and it’s important for every developer.

  9. Sinope says:

    Thanks !!
    it’s a wonderful tutorial

  10. Andy says:

    This tutorial really helped me with jquery, after watching the 15 Days of JQuery screencasts I managed to fix a problem I had with the tooltips stuttering by changing :

    $this.hover(function()

    $this.stop().hover(function()

    This stopped the animations overlapping when tooltips were close together

  11. jack says:

    NOT Wokring IN IE 6

    PNG DOES’nt transparent….

    but its Nice tutorial.

    Any ONE KNOW HOW 2 work on IE 6…

  12. I’m trying to get better at jQuery at this tutorial has just helped me a bunch.

  13. Zoran says:

    Great tut! Anyway, I’m looking for solution to get some content into this cloud … I want to put some icons (for RSS and SiteMap) and links for it … do I have some possibility with this script?

  14. Francesco Aloisio says:

    Great Tutorial, is there anyway to load content to populate the tooltip with an external file? Just like this script does?
    thanks :-)

  15. Francesco Aloisio says:

    Great Tutorial, is there anyway to load content to populate the tooltip with an external file? Just like this script does>>http://www.codylindley.com/blogstuff/js/jtip/?
    thanks :-)

  16. Alvi says:

    Nice work,
    but is there a possibility to change the text without reloading the whole page?

  17. DynamicGuru says:

    Nice one…Some issues with IE 6 though,,,
    i really hate IE 6 (and its creators too)

    • Mike says:

      What kind of issues are you getting? I found that the central part of the tooltip didn’t show on IE6 so I made it a .gif file instead, and that fixed it. And yes, IE is the bane of my life too.

  18. James says:

    Nicely done! There is an issue when you load the page and you hover over one of the clouds to see where the tooltip loads, then resize your browser and hover again and you’ll see that the tip moves… is there anyway to lock it relative to where it’s hovering from?

  19. RaMo says:

    Very Very Good.
    Very useful .

  20. Hrishi says:

    amazing…cool tool tips

  21. anna says:

    I tried your tooltip script on my web page. There is no tooltip appeared inside the tabbed panels but it works outside the tabbed panels on the same page. How do I do a turnaround for the tabbed panels?

  22. Nitin says:

    Very Nice Tooltip.. By far one of the best tooltip.

    I just have to add one thing. It would have been better if you could have shared the PSD file of the image used in tooltip.
    This would allow us to customize the way tooltip looks…

    If you can share it please mail it me.

  23. Joe says:

    This should come in useful!

  24. giancarlo says:

    If i want to remove the tooltip, can i do it?
    For example, after 1 minute, dont show the tooltip… it’s possible?

  25. After reading this tutorial, I am not bored as I was a few minutes ago

  26. Alvin says:

    Great tutorial!
    For those who haven’t figured out the problem of resizing windows and the tip does not reposition itself, then the solution is basically re-calculate the offset every time the mouse hovers:

    code:
    /*
    var offset = $(this).offset();//move inside the mouse over fn
    var tLeft = offset.left;//move inside the mouse over fn
    var tTop = offset.top;//move inside the mouse over fn
    //var tWidth = $this.width();//not referenced therefore not needed
    //var tHeight = $this.height();//not referenced therefore not needed
    */

    /* Mouse over and out functions*/
    $this.hover(
    function() {
    var offset = $(this).offset();
    tipInner.html(tTitle);
    setTip(offset.top, offset.left);
    setTimer();
    },
    function() {
    stopTimer();
    tip.hide();
    }
    );

  27. Alvin C says:

    Great tutorial!
    For those who haven’t figured out the problem of resizing windows and the tip does not reposition itself, then the solution is basically re-calculate the offset every time the mouse hovers:


    /*
    var offset = $(this).offset();//move inside the mouse over fn
    var tLeft = offset.left;//move inside the mouse over fn
    var tTop = offset.top;//move inside the mouse over fn
    //var tWidth = $this.width();//not referenced therefore not needed
    //var tHeight = $this.height();//not referenced therefore not needed
    */

    /* Mouse over and out functions*/
    $this.hover(
    function() {
    var offset = $(this).offset();
    tipInner.html(tTitle);
    setTip(offset.top, offset.left);
    setTimer();
    },
    function() {
    stopTimer();
    tip.hide();
    }
    );

  28. yxwang says:

    So how can the width set to auto growth, I am English is not very good, do not know if you can understand not?

  29. Emrul Hasan Anni says:

    This is a very nice and easy-setup tooltip. I want to know about 2 things.
    1st – the tooltip disappears if the cursor is over the tooltip. It should not disappear if the cursor over it and
    2nd – browser resizing problem. the position does not change if i scroll down.
    is there any solution to these problems?

    • Michael says:

      I’m having this same issue (#1), Emrul. The tooltip only shows up if I move my cursor in an upward direction to allow the tooltip to show up where my cursor was. If I just move the cursor over the image that has the tooltip and don’t move my mouse up, the tooltip doesn’t show up (though my cursor switches from the pointer to the text-select cursor).

      Did you figure this out???

    • Michael says:

      Nevermind! (sort of)

      Realized that since the div class=”tip” that jQuery prepended fires the hover-out if you position the tooltip over the image that has the anchor tag around it…

      I cheated and put a link under the image, but I’d be curious if there was a way to prevent the .tip div from firing the exit part of the hover function…

  30. Norris says:

    Im using this tooltip on an image map, I can get the image tooltip to appear but only on the top of the image, NOT OVER the image maps. The image maps are beside each other. NEED HELP PLEASE.

    Here is the CSS

    .tip {
    font-family:Arial, Helvetica, sans-serif;
    font-size:11px;
    width: 212px;
    padding-top: 37px;
    overflow: hidden;
    display: none;
    position: absolute;
    z-index: inherit;
    background: transparent url(images/tipTop.png) no-repeat top;}

    .tipMid {background: transparent url(images/tipMid.png) repeat-y; padding: 0 25px 20px 25px;}
    .tipBtm {background: transparent url(images/tipBtm.png) no-repeat bottom; height: 32px;}

    Here is the .js file

    $.fn.betterTooltip = function(options){

    /* Setup the options for the tooltip that can be
    accessed from outside the plugin */
    var defaults = {
    speed: 200,
    delay: 300
    };

    var options = $.extend(defaults, options);

    /* Create a function that builds the tooltip
    markup. Then, prepend the tooltip to the body */
    getTip = function() {
    var tTip =
    “” +
    “” +
    “” +
    “” +
    “”;
    return tTip;
    }
    $(“body”).prepend(getTip());

    /* Give each item with the class associated with
    the plugin the ability to call the tooltip */
    $(this).each(function(){

    var $this = $(this);
    var tip = $(‘.tip’);
    var tipInner = $(‘.tip .tipMid’);

    var tTitle = (this.title);
    this.title = “”;

    var offset = $(this).offset();
    var tLeft = offset.left;
    var tTop = offset.top;
    var tWidth = $this.width();
    var tHeight = $this.height();

    /* Mouse over and out functions*/
    $this.hover(
    function() {
    var offset = $(this).offset();
    tipInner.html(tTitle);
    setTip(offset.top, offset.left);
    setTimer();
    },
    function() {
    stopTimer();
    tip.hide();
    }
    );

    /* Delay the fade-in animation of the tooltip */
    setTimer = function() {
    $this.showTipTimer = setInterval(“showTip()”, defaults.delay);
    }

    stopTimer = function() {
    clearInterval($this.showTipTimer);
    }

    /* Position the tooltip relative to the class
    associated with the tooltip */
    setTip = function(top, left){
    var topOffset = tip.height();
    var xTip = (left+20)+”px”;
    var yTip = (top-topOffset+28)+”px”;
    tip.css({‘top’ : yTip, ‘left’ : xTip});
    }

    /* This function stops the timer and creates the
    fade-in animation */
    showTip = function(){
    stopTimer();
    tip.animate({“top”: “+=20px”, “opacity”: “toggle”}, defaults.speed);
    }
    });
    };

  31. Jonathan says:

    Isnt there a quickway so that the tooltip will always centers of the link?

  32. Senthil Raj says:

    The way you explained your code is so good. your plugin is very useful. expecting many more useful stuffs from you. All the best :-)

  33. Eric says:

    Great tut …
    Qstn: How can I get the tooltip to persist after hovering out of the link to the tooltip, say I wanted to put a link in the tooltip that can be accessed?

  34. very cool! Hi from Sarajevo!

  35. yasamphani says:

    Thanks for the feedback…@@@!!!

  36. fudo says:

    How can you move the position of the tool tip. Lets say I want each section to appear in one place? please let me know.

  37. brandon says:

    can someone explain how to show a tooltip on page load for perhaps a couple seconds, so the user is alerted to a new link. I have the tooltips working on mouseover on the links but i cant figure out how to call into the functions to either showTip() or something like that on page load, maybe it’s not built for that?

    thanks in advance.

  38. Nice work,
    but is there a possibility to change the text without reloading the whole page?

  39. Awesome tutorial and very nice rollover bubble image.

    thanks man really nice

  40. Brandon says:

    I hope this helps someone else. I was using ASP.net update panels and found two problems. one of which was fixed by the comment mentioned earlier about using $this.stop().hover(), I actually added another line into the hover event to stop the timer so my code now looks like this.
    $this.stop().hover(
    function() {
    tipInner.html(tTitle);
    stopTimer();
    setTip(tTop, tLeft);
    setTimer();
    },
    function() {
    stopTimer();
    tip.hide();
    }
    );

    The second issue was that the content of the div for the actual popup text was disappearing when i clicked and updated a different updatepanel than the ones where the popups appear. To fix this I had to also call the update method on the updatePanel which contains the popup tooltips. (although that content technically had not changed)

    like i said i hope this helps someone, because it frustrated me.

  41. Brandon says:

    Has anyone had this problem?

    If the tooltip controls are in an asp.net updatepanel and updates are performed too quickly (read double clicking) then the tooltips animation just repeats forever and the tooltip scrolls itself down the page forever.

  42. WhiteNexus says:

    How do you change the font size?

  43. Azeem Michael says:

    nice, I like!

  44. Alexandre says:

    This is an excellent jQuery plugin. I enjoyed a lot it.

  45. Website Girl says:

    Hey, I am still only getting the old “Titles” no hover tip boxes.. can enayone help???

    TA

  46. Spelen says:

    Another lovely jaquery solution, nice option with the delay ;-)

    Great Job!

  47. Bryan says:

    This is awesome. I have been struggling with the positioning though. I would like to have to tool tip underneath rather than above the element. I am sure that this is easy and with only a few lines of code for the position I am not sure why it has been so difficult for me, but it hasn’t worked for me yet. Any help would be greatly appreciated.

  48. levani says:

    How can I make it possible to keep the tooltip open when the mouse is over it? Now when the mouse is out of the link it closes automatically! For some reasons I want to keep it opened if the mouse is over the tooplip itself! Can anyone please help?

  49. dubbs says:

    Hiya,

    Is it possible to allow the tooltip to sit centre aligned above the span it is being called from? Hard-coding this in the jQuery seems a poor solution here… I am having a play at trying to solve this but any help would be greatly received!

    var xTip = (left-70)+”px”;

    This is how the default is coded – but it means that the toptip will fade in 70px from the left edge of your tTip span – not sit in the center of its width…

    any ideas?

    Cheers dubbs.

Comment Page 2 of 3 1 2 3

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.