Building your own lightbox – part 1

Javascript, 23 July 2008, 35 comments

A lightbox is a way of showing an image, a movie or an entire web page as an overlay on a website. It is often used in gallery style websites and for portfolio’s. This article will look into the basics of building your own lightbox for images.

Part 2, published next week, will look into some of the cooler stuff:

Why an article on making a lightbox?

I know, I know, there are a lot of really good lightbox scripts out there already (check out the comparison matrix!) However, during my internship I developed a website that needed some very specific lightbox effects, and none of the existing lightbox scripts did what I wanted them to do. It was really fun to build one on my own, so I thought I’d let you share in the excitement ;)

Let’s get started!

Whenever I develop something, I first take a couple of steps back and make a list of all the actions that I need to perform that together make the complete effect I want to achieve.

The actions that happen when opening a lightbox:

  1. User clicks on a link designated as a lightbox link
  2. A Javascript event handler picks up on it
  3. Two extra elements get added into the DOM:
    • A 100% width and 100% height overlay
    • A container for the image/movie/page getting loaded
  4. overflow-y:hidden gets added to the body to prevent scrolling
  5. An ajax call is made to retrieve the href of the link
  6. Javascript makes the loaded content visible and positions it as soon as it’s loaded
  7. The Javascript does a return false to make sure the regular link doesn’t fire as well

jQuery, the library I used to develop the lightbox, makes it trivially easy, so lets start. Throughout the article, we’ll be working with this link:


<a href="http://kilianvalkhof.com/uploads/lightbox.jpg" class="lightbox">open lightbox!</a>

1. The event handler


$(".lightbox").click(function() {
	window.startOverlay();
});

“Find the elements with class “lightbox”, and if someone clicks on one of them, execute the function window.startOverlay.”

The only problem with the code above is that I don’t specify which link gets clicked. So we have to get the contents of the href attribute and send it along as a parameter:


$(".lightbox").click(function(){
	overlayLink = $(this).attr("href");
	window.startOverlay(overlayLink);
});

2. Get the DOM ready

As I said in the list above, I need two new elements, and i need to prevent the viewport from scrolling.


function startOverlay(overlayLink) {
	$("body")
		.append('<div class="overlay"></div><div class="container"></div>')
		.css({"overflow-y":"hidden"});
	…
}

Now all the needed elements are in the DOM and ready to be used. However, the newly made elements have no style yet, so we need to add some CSS to our stylesheet:


.overlay {
	position:absolute;
	top:0;
	left:0;
	height:100%;
	width:100%;
	background:#000;
	opacity:0;
	filter:alpha(opacity=0);
	z-index:50;
}
.container {
	position:absolute;
	opacity:0;
	filter:alpha(opacity=0);
	left:-9999em;
	z-index:51;
}

The two odd things here are the fact that all opacity is set to zero, and that .container is way, way to the left. That is because the actual content hasn’t loaded yet, so we just hide it all for now.

We need to make the semitransparent overlay visible however, and for that we use a fade. (You can use any other animation too, but the fade-in just looks the best, IMO);


function startOverlay(overlayLink) {
	…
	$(".overlay").animate({"opacity":"0.6"}, 200, "linear");
	…
}

This tells jQuery to animate the opacity from the current value (zero) to 0.6, do so in 200 milliseconds, and have a linear transitions (part 2, next week, will look into some of the other possible transitions)

After this has happened, we need to load in the content to put in the lightbox.

3. The Ajax call

I’ll tell you a little secret. For the loading of an image, You don’t actually need an ajax call! You just add the image to the DOM and your browser downloads it automatically.

The “Ajax” bit is just this:


function startOverlay(overlayLink) {
	…
	$(".container").html('<img src="'+overlayLink+'" alt="" />');
	…
}

The overlayLink is the link of the clicked element that we added into the function as a parameter when someone clicks a link. It doesn’t work like this with web pages, but we’ll write something for that, next week.

4. Make it visible

We now have everything set for the grande finale: actually displaying the image!

We need only a little information: the width and height of the image. Then we position the container in the middle of the screen, and fade it in. However, we can’t just request it, It might still be downloading and then we get the wrong or no dimensions at all. So before doing anything, we need to check whether it has downloaded completely, and only then request the dimensions. Luckily, that is fairly easy:


function startOverlay(overlayLink) {
	…	
	$(".container img").load(function() {
		var imgWidth = $(".container img").width();
		var imgHeight = $(".container img").height();
		$(".container")
			.css({
				"top":        "50%",
				"left:        "50%",
				"width":      imgWidth,
				"height":     imgHeight,
				"margin-top": -(imgHeight/2),
				"margin-left":-(imgWidth/2) //to position it in the middle
			})
			.animate({"opacity":"1"}, 200, "linear");
	});
}

The load function get executed as soon as the image has loaded fully. When the image is loaded, we get the right dimensions, position the image and, last but not least, make the image available with a nice fade.

5. return false;

Now that everything is successful, and you have a working lightbox, you just need to do one last thing: make sure the browser doesn’t also load the link itself!


$(".lightbox").click(function() {
	window.startOverlay();
	return false;
});

Done!

That’s it, now we’re done. We have a working lightbox and all our users are happy.

Not…?

…Oh!

Allowing the user to close the lightbox.

Of course, a user must be able to close an lightbox as well. This usually happens when someone clicks next to the image, so we’ll take that method for now. (We’ll expand on it in part 2.) The actions for closing a lightbox:

If you’ve stuck around ’till here, I think you can manage the code at once:


$(".overlay").click(function(){
	$(".container, .overlay")
	.animate({"opacity":"0"}, 200, linear, function(){
		$(".container, .overlay").remove();	
	})
});

and for the css, add cursor:pointer; to the .overlay element to give people a visual clue that they can click it.

Pretty easy, no? You can actually define multiple elements in your jQuery selector. Just like in CSS, you can do so with just a simple comma.

The only gotcha here, is that you need to make sure this bit of code is within your lightbox function (see the full example below to see what I mean) otherwise it will not get executed.

Full code

To see the full code put together, check out the Demo page.

Remember, next week, we’ll expand on this a whole lot more, including some very cool stuff like nice animations and multiple lightboxes! See you then! :)