PxO Ink

Icebox

A jQuery Alternative To The "Lightbox" Image Hovering Effect

Written By: PxO Ink on August 8th, 2011.

jQuery defines itself as:

...a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.

jQuery is an extremely useful library which makes working with JavaScript quick, easy and painless. This article will show you how to create the "Lightbox" effect using jQuery and a few functions. Welcome to Icebox. September 19th, 2011. I realize that there are jQuery plugins that mimic the "Lightbox" effect very well, however, this is primarily an introduction and investigation into one of the many ways that effect can be reproduced.

Icebox is nowhere near as powerful as Lightbox 2. Lokesh Dhakar has created something truly great, with cross-browser compatibility and a sleek UI. It's definitely worth the download.

Most of the positioning of the final element is done through JavaScript; to insure that it's always accurate to the image dimensions and location on screen. However, some things must be set through CSS:


#icebox {
	display: none;
	position: absolute;
	padding: 1.50em;
	background-image: url('../images/icebox-background.png');
	text-align: right;
	}


#icebox img {
	display: block;
	margin-top: 1.00em;
	margin-bottom: 1.00em;
	}

Setting the element's display property to none is mandatory to allow for the jQuery fading effects. Setting the positioning to absolute is also mandatory for styling the element in the center of the viewbox. The image is also set to display as a block element, to provide an essential line-break.


#icebox a {
	padding: 0.25em;
	padding-left: 0.75em;
	padding-right: 0.75em;
	background-color: #EEE;
	border-width: 1px;
	border-style: solid;
	border-color: #000;
	font-size: 1.50em;
	font-weight: bold;
	font-variant: small-caps;
	text-decoration: none;
	text-transform: lowercase;
	}

#icebox a:hover {
	color: #000;
	background-color: #F00;
	text-decoration: none;
	}

There will also need to be some sort of way to close the Icebox after it's loaded. As such, the anchor tag has been styled appropriately.

Finally! It's time to get to the JS! To facilitate a better learning experience, this article will work backward:


function closeElement(ID) {
	//Fade and close the element.
	jQuery(ID).fadeOut('medium', function() {
		jQuery(ID).remove();
	});
}

The close element function does exactly what it's name implies. First, a fadeOut call is made through the jQuery library to provide a fading out effect on the element. Afterward, the element is removed from the webpage. Of course, the element should fade out completely before it's removed. By adding a function within the fadeOut call, jQuery essentially waits until the fadeOut call is completed before it calls for the element to be removed.


function centerElement(ID) {
	jQuery(ID).css("top", (((jQuery(window).height() - jQuery(ID).outerHeight()) / 2) + jQuery(window).scrollTop()));
	jQuery(ID).css("left", (((jQuery(window).width() - jQuery(ID).outerWidth()) / 2) + jQuery(window).scrollLeft()));
}

Centering the element is also a very important part of the Icebox. Aesthetics, with function, must flow together for the end product to be acceptable. The following calculation is made and applied to the top and left CSS properties:

Top = ((Window Height - Object Outer Height) / 2) + Scroll Height from Top
Left = ((Window Width - Object Outer Width) / 2) + Scroll Width from Left

The outer height and widths are necessary, as padding, margins and borders may be used which would skew the final centering if not taken into consideration.

While this specific function is incredibly simple, it can be modified and expanded so checks are made to improve upon the centering functionality. For instance, if you were so inclined, testing for whether or not the window height is greater or less than the Icebox height and adjusting for that is a possibility.


function icebox(obj) {
	//Declare variables.
	var	img	=	jQuery(obj).attr('href');
	var	title	=	jQuery(obj).attr('title');
	var	markup	=	new Array();

There are three variables that need to be declared: the image source, the title, and the markup array.


	//Assemble markup.
	markup.push(
		'<div id="icebox">',
		'<a href="#icebox" title="Close" onclick="closeElement(\'#icebox\')">X</a>',
		'<img id="icebox-loading" src="images/icebox-loading.gif" alt="Loading..." title="Loading..." />',
		'<img id="icebox-image" src="' + img + '" alt="" title="' + title + '" />',
		'</div>'
	);

One method for creating extensive HTML markup within JS is pushing slices together into an array. This method provides an easy way to read code and modify it at a later date. This specific markup consists of a single div, an anchor which provides a way to remove the element, a placeholder loading animation and the image.


	//Join markup to implement the new element.
	jQuery('body').append(markup.join(''));

	//Hide the image until it's loaded.
	jQuery('#icebox-image').hide();

	//Position the element in the center.
	centerElement('#icebox');

The HTML is joined together into code that the browser can interpret. This code is appended into the body element. There's a strong chance, especially with larger images, that it will take a few moments for the user to download. To insure that centering is maintained aesthetically, the image is hidden, and the element is centered using the loading animation as a reference.


	//When the image has loaded.
	jQuery('#icebox-image').load(function() {
		//When the loading image has faded out.
		jQuery('#icebox-loading').fadeOut('medium', function() {
			//Fade the image in.
			jQuery('#icebox-image').fadeIn('medium');

			//Position the element in the center.
			centerElement('#icebox');
		});
	});

	//Fade the new element in.
	jQuery('#icebox').fadeIn('medium');

The most complicated part of the function isn't really all that complicated; it only looks that way because there is a sequence of events that must be maintained in order. To keep the element aesthetically pleasing, it's important to insure that each fading animation is completed before the next event takes place. The nesting provides the following sequence of events:

  1. When the image is loaded

    1. Fade the loading animation out, and when that is completed

      1. Fade the image in

      2. Center the element

Finally the element is faded into view.


	//Return false to stop default event.
	return false;
}

An intervention into the standard functionality must take place as to not direct the user to the actual image. By default, clicking on a link to an image will open that image in the browser, or in an application chosen by the user.

The following is HTML markup to launch the Icebox:


<a href="images/icebox-demo-full.gif" title="Icebox Demonstration" onclick="return icebox(this)">
	<img src="images/icebox-demo-thumb.gif" alt="thumbnail" title="Icebox Demonstration Thumbnail" />
</a>

Here the icebox function is returned after the current anchor data has been sent. Note the most important part of the HTML markup is the return of the icebox function. Without this, the intervention mentioned earlier will not succeed.

Demonstration:

thumbnail thumbnail

Thank you for reading and if you have any questions, please feel free to send an email.