Video icon 64
Learning to code? Skill up faster with our practical video courses. Start your free trial today.
Advertisement

Build a Better Tooltip with jQuery Awesomeness

by
Student iconAre you a student? Get a yearly Tuts+ subscription for $45 →

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:

	<a href="#" title="This is the tooltip text">This is a link</a>

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.


Advertisement