EDIT: There has been a report of this code not working in IE6. Well turns out it didn’t work in any of the IE browsers. Click here to jump to the fix.

This post is all about how to make a image preload (load in the background) and then animate the box it will fit in to match it’s size.

I’ll post a link to an example at the end, but first lets get down to the coding. First you’ll need jQuery, most of you probably know where to get it but if not you can download the latest version from jQuery’s Google code site.

The HTML

So let’s go. First we want to set up so HTML. Let’s go simple:

<div id="gallery">
    <div id="loader" class="loading"></div>
</div>

There we go. It’s very simple. We have a <div> with the id ‘gallery’ to contain everything, then we have another <div> with the id of ‘loader’ & the class ‘loading’. I’ll explain why in a minute.

The CSS

Ok, now let’s go on to the CSS. I’ll show the code first and then explain it:

body {
	background-color:black;
}
#gallery {
	width:500px;
	margin:0 auto;
	padding:0;
}
div#loader {
	width: 300px;
        height: 400px;
	border: 3px #ccc double;
}
div#loader.loading {
	background: url(img/24-1.gif) no-repeat center center;
}

Well the body bit is obvious. :) The id ‘gallery’ just centers it using auto margins and gives a width of 500px. Then id ‘loader’ gives a permanent width & height to the loader and a border of 3px with a double effect in gray, obviously you can change them as you wish. We then define a ‘loading’ class only to work when added to the div with the id ‘loader’. This loads a background gif, an animated loader, to signify that the image is loading. You can get the loader I used & lots of other AJAX style loaders at ajaxload.info

The jQuery

Next comes the hard bit. Well it’s only hard if you don’t know how. :)

$(function() {
  var img = new Image();
  $(img).load(function() {
    $(this).hide();
    $('#loader').removeClass('loading').html(this);
    $('.fullSizeImage').wrap('<a></a>');
    $('#loader a').attr('href', 'path/to/img/');
    iHeight = $('.fullSizeImage').height();
    iWidth = $('.fullSizeImage').width();
    if($('#loader').height() == iHeight && $('#loader').width() == iWidth) {
	$(this).fadeIn();
    } else {
	$('#loader').animate({height: iHeight}, 500).animate({width: iWidth}, 500);
	$(this).animate({opacity: 1}, 1000).fadeIn();
    }
  }).attr('src', 'path/to/img').addClass('fullSizeImage');
});

So first we go inside jQuery’s on DOM ready function. This is a short hand way of writing it, for more on what exactly the ready function is try here.

We then create a new image and store it as img. Then hand that img as a jQuery selector, since it doesn’t yet exist this tells jQuery to create it. We then ask it to do a few things when the image has finished loading. First we hide the image from view, this is so we can make some fancy transitions, then we ask jQuery to target the element with the id ‘loader’ and remove the ‘loading’ class. This will remove the loading animation, we want this to happen since the image has finished loading, we then tell it to place this (which refers to the image) into the HTML of the div ‘loader’.

Next we target something with a class called ‘fullSizeImage’. Now this might seem odd but we add that class to the image we are creating later in the code, we can reference it now since it will have already executed the later commands before it does these ones. We tell jQuery to wrap an %lt;a> around it. Then we target the <a> inside the ‘loader’, of which there is only one, and give it a path to the full size image. Since our gallery will be pretty it can’t show the full image only a scaled down one, this is why we give the user the option to click and see the full image.

We then get the height and the width of ‘fullSizeImage’, which is the image, and store it in 2 variables. You can get the width & height of most elements including images using the function shown. We then ask if the width & height of the image are both exactly the same size as the ‘loader’ container. If they are then there is no point in resizing, so we fade the image in nicely. If not we use the jQuery animation function to animate the height & then the width, if needed. You could do both at once by adding them to the same animation function, but I think seperate looks better. Then we fade in the image.

Since we used hide() to hide the image, we have to use fadeIn() to get the image back, but fade doesn’t queue onto the animate function, basically the image would fade in and resize at the same time and that’s not what we want. To solve this we get jQuery to animate a useless property for the length of time of both resizes, in this case 1 second. You could also possibly use jQuerys ‘:animated’ selector (jQuery 1.2 above) but I’ll leave that for another tutorial.

Next you could give it something to do in case it can’t load the image by using:

.error(function() {
  //things here
})

just before attr(), but I have left it out. Next we set the path to the image we want to load, this is more than likely the full image just resized by CSS, which you can do using the following:

selector img {
  width: 300px;
  height: auto;
}

where selector is a element, id or class limiter, or you can do it like I have in this example using the attr to add a set width or height to the <img> tag. Finally we add the class of ‘fullSizeImage’.

This all may seem a little confusing and to be honest it’s hard to explain in typed words what exactly is going on, but I hope that what I have wrote makes some sense and helps you understand how exactly this code works.

This is, as you might have guessed, an excerpt from an image gallery prototype I am still working on for my sisters, Ebay Artist Lisa-Marie, new website. I’m not showing it all since I’m not exactly finished yet but this bit I am happy with, to some extent. If you can see any bugs or you just can’t get it to work then please leave a comment or if you have MSN contact me via that for a instant response. ;)

You can view a fully implemented demo here. It could look nicer but it works & aesthetics isn’t exactly my forte. The images are of Californian pop duo Aj & Aly, if you were wondering.


FIX: Here’s how to fix that problem with the Internet Explorer browsers. You need to completely change the code to the following:

$(function() {
if($('#loader:animated').length != 0) {
		return false;
	} else {
		var img = new Image();
		$(img).load(function() {
			$(this).hide();
			$('#loader').removeClass('loading').html(this);
			$('.fullSizeImage').wrap('<a class="fullImageLink"></a>');
			$('#loader a').attr('href', imgPath);
			$(this).css({"height": 'auto', "width": 400});
			iHeight = $(this).height();
			lHeight = $('#loader').height();
			if(lHeight == iHeight) {
				$(this).fadeIn();
			} else {
				tempImg = $(this);
				$('#loader').animate({height: iHeight}, 500).animate({width: 400}, 500, function() {
					$(tempImg).fadeIn();
				});
			}
		}).attr('src', imgPath).addClass('fullSizeImage');
	}
}

This is the second time I have changed the code thanks to the pain in the royal ass that is Internet Explorer. I suppose I should thank it though as it pointed out a slight flaw in the code, well I say flaw, it was actually IE’s inability to understand a certain part of code… I hate that browser. :(

Anyway a huge thank you to Nat for showing me & making me aware of the errors in my code. :) I said I would fix it and hopefully I have. It has been tested to the best of my ability in IETester but since I have Vista I can’t truly test the code in IE6. Oh and the new bit about :animated means it requires the newest version of jQuery and also stops IE from having a sh*t fit when pressing lots of thumbnails at once, which you shouldn’t do anyway, but should that happen it won’t break. :)

Anyway hopefully that has fixed it, you can now see a fully featured version of this code running over at Lisa-Marie Art. Enjoy. :)