Tutorialzine - jQuery HTML5 CSS3 PHP MySQL tutorials, resources and freebies.

An Awesome CSS3 Lightbox Gallery With jQuery

Posted on Nov 23rd, 2009
  • CSS
  • jQuery
  • PHP
DemoDownload

In this tutorial we are going to create an awesome image gallery which leverages the latest CSS3 and jQuery techniques. The script will be able to scan a folder of images on your web server and build a complete drag and drop lighbox gallery around it.

It will be search-engine friendly and even be compatible with browsers which date back as far as IE6 (although some of the awesomeness is lost).

We are using jQuery, jQuery UI (for the drag and drop) and the fancybox jQuery plugin for the lightbox display in addition to PHP and CSS for interactivity and styling.

Before reading on, I would suggest that you download the example files and have the demo opened in a tab for reference.

So lets start with step one.

Step 1 – XHTML

The main idea is to have PHP as a back-end which will generate the necessary XHTML for each image. The generated code is later included in demo.php and completes the gallery XHTML front-end.

demo.php

<!-- The gallery container: -->
<div id="gallery">

<?php
/* PHP code, covered in detail in step 3 */
?>

<!-- The droppable share box -->
<div>
</div>

</div>

<div></div>

<!-- This is later converted to the modal window with the url of the image: -->
<div id="modal" title="Share this picture">
<form>
<fieldset>
<label for="name">URL of the image</label>
<input type="text" name="url" id="url">

Nothing too fancy here. Notice the modal div – it is used to generate the modal window that is shown when the user drops a picture on the share box. But more on this later on.

spacer

The gallery

Step 2 – CSS

Now that we have all the markup in place, it is time to style it. First we need to include the CSS files in the head section of the page.

demo.php

<link rel="stylesheet" type="text/css" class="demo.css" />
<link rel="stylesheet" class="ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-darkness/jquery-ui.css" type="text/css" media="all" />
<link rel="stylesheet" type="text/css" class="fancybox/jquery.fancybox-1.2.6.css">

After we’ve done that, we can start writing the styles.

demo.css

body{
	/* Styling the body */
	color:white;
	px;
	background: #222222;
	font-family:Arial, Helvetica, sans-serif;
}

#gallery{
	/* The pics container */
	%;
	px;
	position:relative;
}

.pic, .pic a{
	/* Each picture and the hyperlink inside it */
	px;
	px;
	overflow:hidden;
}

.pic{
	/* Styles specific to the pic class */
	position:absolute;
	border:5px solid #EEEEEE;
	border-bottom:18px solid #eeeeee;

	/* CSS3 Box Shadow */
	-moz-box-shadow:2px 2px 3px #333333;
	-webkit-box-shadow:2px 2px 3px #333333;
	box-shadow:2px 2px 3px #333333;
}

.pic a{
	/* Specific styles for the hyperlinks */
	text-indent:-999px;
	display:block;
	/* Setting display to block enables advanced styling for links */
}

.drop-box{
	/* The share box */
	px;
	px;
	position:absolute;
	bottom:0;
	right:0;
	z-index:-1;

	"attachment_527" style="px">spacer 

The pics explained

Step 3 – PHP

As you remember, in step 1 we covered the XHTML part and mentioned that PHP is responsible for generating the markup that comprises the individual images. And here is how this is actually done:

demo.php

/* Configuration Start */
$thumb_directory = 'img/thumbs';
$orig_directory = 'img/original';
$stage_;
$stage_;
/* Configuration end */

$allowed_types=array('jpg','jpeg','gif','png');
$file_parts=array();
$ext='';
$title='';
$i=0;

/* Opening the thumbnail directory and looping through all the thumbs: */
$dir_handle = @opendir($thumb_directory) or die("There is an error with your image directory!");
$i=1;

while ($file = readdir($dir_handle))
{
	/* Skipping the system files: */
	if($file=='.' || $file == '..') continue;

	$file_parts = explode('.',$file);
	$ext = strtolower(array_pop($file_parts));

	/* Using the file name (withouth the extension) as a image title: */
	$title = implode('.',$file_parts);
	$title = htmlspecialchars($title);

	/* If the file extension is allowed: */
	if(in_array($ext,$allowed_types))
	{
		/* Generating random values for the position and rotation: */
		$left=rand(0,$stage_width);
		$top=rand(0,400);
		$rot = rand(-40,40);

		if($top>$stage_height-130 && $left > $stage_width-230)
		{
			/* Prevent the images from hiding the drop box */
			$top-=120+130;
			$left-=230;
		}

		/* Outputting each image: */
		echo '
		<div id="pic-'.($i++).'" style="top:'.$top.'px;left:'.$left.'px;">

		<a rel="fncbx" class="'.$orig_directory.'/'.$file.'" target="_blank">'.$title.'</a>

		</div>';
	}
}

/* Closing the directory */
closedir($dir_handle);

First, we open the thumbnail directory with opendir (using the @ modifier to prevent any possible errors from getting shown to the user) and looping through all the images.

In the loop, we skip the non-image files and generate some XHTML code for each image, which is directly printed to the screen.

As mentioned in the CSS part, PHP handles the rotation and scattering of the images on the page. Each image is positioned at random X and Y coordinates, and rotated in an angle between -40 and 40 degrees (to prevent upside-down images). Those are generated with the use of the rand() PHP function and included as CSS styles in the picture’s style attribute.

There are two image folders used by the gallery – thumbs, which holds the 100×100 px thumbnails, and original, which holds the big versions of the images. It is important that the thumbnail and original image have the same name, otherwise the gallery won’t function properly.

The only thing left is to throw in some interactivity.

Step 4 – jQuery

We now have a good looking CSS gallery on our hands. But that means nothing if we cant drag the pretty pictures around the screen and zoom them in a fancy lightbox display, does it?

This is where jQuery comes into play.

script.js

$(document).ready(function(){
	// Executed once all the page elements are loaded
	var preventClick=false;
	$(".pic a").bind("click",function(e){

		/* This function stops the drag from firing a click event and showing the lightbox */
		if(preventClick)
		{
			e.stopImmediatePropagation();
			e.preventDefault();
		}
	});

	$(".pic").draggable({

		/* Converting the images into draggable objects */
		containment: 'parent',
		start: function(e,ui){
			/* This will stop clicks from occuring while dragging */
			preventClick=true;
		},
		stop: function(e, ui) {
			/* Wait for 250 milliseconds before re-enabling the clicks */
			setTimeout(function(){ preventClick=false; }, 250);
		}
	});

	$('.pic').mousedown(function(e){
		/* Executed on image click */
		var maxZ = 0;

		/* Find the max z-index property: */
		$('.pic').each(function(){
			var thisZ = parseInt($(this).css('zIndex'))
			if(thisZ>maxZ) maxZ=thisZ;
		});

		/* Clicks can occur in the picture container (with class pic) and in the link inside it */
		if($(e.target).hasClass("pic"))
		{
			/* Show the clicked image on top of all the others: */
			$(e.target).css({zIndex:maxZ+1});
		}
		else $(e.target).closest('.pic').css({zIndex:maxZ+1});
	});

	/* Converting all the links to a fancybox gallery */
	$("a.fancybox").fancybox({
		zoomSpeedIn: 300,
		zoomSpeedOut: 300,
		overlayShow:false
	});

	/* Converting the share box into a droppable: */
	$('.drop-box').droppable({
		hoverClass: 'active',
		drop:function(event,ui){

			/* Fill the URL text field with the URL of the image. */
			/* The id of the image is appended as a hash #pic-123 */
			$('#url').val(location.href.replace(location.hash,'')+'#' + ui.draggable.attr('id'));
			$('#modal').dialog('open');
		}
	});

	/* Converts the div with id="modal" into a modal window  */
	$("#modal").dialog({
		bgbr: true,
		modal: true,
		autoOpen:false,

		buttons: {
			Ok: function() {
				$(this).dialog('close');
			}
		}
	});

	if(location.hash.indexOf('#pic-')!=-1)
	{
		/* Checks whether a hash is present in the URL */
		/* and shows the respective image */
		$(location.hash+' a.fancybox').click();
	}
});

First we are binding a click function to the images, which prevents the lightbox from showing once we start dragging the pic around.

After this we make all the pictures draggable, and then we set up the lightbox.

Later we turn the “Drop to share” box into a droppable, which enables it to detect when a picture is hovered and dropped. This allows us to add a special hover style to the container, and to open the modal window on drop.

The modal window itself is a user interface component that comes with jQuery UI. It hides all the page elements under a semi-transparent overlay, and thus blocking them for the user. The only thing occupying the their attention is the message window, which in our case holds the text box with the URL of the image, as defined in the div with id of modal in step one.

Last, we have a few lines of code which check whether a hash of the type #pic-123 is present in the URL, which would cause the respective image to be shown in the lightbox on page load.

With this our awesome CSS3 gallery is complete!

Conclusion

Today we created a fancy gallery, which uses a wide set of web technologies to bring you a new kind of dynamic experience.

In addition, it is extremely easy to add to an existing site – you just need upload it and provide a folder with images, no databases required.

You are free to modify and use this gallery in your own sites. Be sure to share all your awesome creations based on this gallery with the community via our Tutorial Mash-ups (above the comment section).

Also, if you enjoyed this article, you might want to subscribe to our RSS feed or follow us on twitter.

spacer

by Martin Angelov

Martin is a web developer with an eye for design from Bulgaria.

He founded Tutorialzine in 2009 and is publishing new tutorials weekly.

Related Tutorials

67 Comments

  1. spacer Marco says:
    November 23, 2009 at 12:53 pm

    This reminds me a lot about my polaroid photo viewer, except this one has the "click to zoom" effect implemented (something I didn't do). My version also rotates the polaroids once you've dropped them :) .

    Well done and thanks for sharing!

    Reply
  2. spacer says:
    November 23, 2009 at 1:45 pm

    A great, great, great, great, great tutorial ! As usual...
    I'm just wondering how is going to be when you'll come out with a "medium" quality article because we get used to premium quality here...
    Thanks !

    Reply
  3. spacer Martin says:
    November 23, 2009 at 2:36 pm

    A great photo viewer, Marco! Now that I look at it they do look similar.
    Thanks for sharing the link, I am sure that the readers would love to see your implementation.

    Thanks for the comment, Jµ, I appreciate it!

    Reply
  4. spacer Michael Langham says:
    November 23, 2009 at 4:07 pm

    Again Martin, BRAVO.

    Serendipity too, as I 'just-now' got off the phone with a client that forever has champagne ideas with but a beer budget (ironically coincidental, he's a sports-bar general manager)

    He wanted ability to upload photos from 'events' they have, with photos showing on his site. With a little tweaking, marrying the style of the existing site with elements of the tutorial, this should fit the bill. (no pun, please)

    So, again, thanks again for a well-written and timely tutorial.

    Reply
  5. spacer Paul rostorp says:
    November 24, 2009 at 4:30 am

    Great tutorial! But it would look even better if the image rotated when you grabbed it, using the jquery rotate plugin.

    Reply
  6. spacer Mike McMurray says:
    November 24, 2009 at 11:50 am

    This sort of thing is great. It'll increase it's "awesomeness" once more people have multi-touch screens and can move the photos around with their hands. Nice work Tutorialzine.

    So much better to do it it a normal browser than forking out $10k or more for a Surface table.

    Reply
  7. spacer Sergio Almeida says:
    November 24, 2009 at 6:13 pm

    Very nice. Great tutorial too. Thanks for sharing.

    Reply
  8. spacer Ryan says:
    November 24, 2009 at 9:58 pm

    You could use the drag and drop api rather than using jquery ui to emulate drag and drop.

    Reply
  9. spacer Ben says:
    November 25, 2009 at 2:32 am

    Great Tut, thanks for sharing this.
    I only don't quit understand the SHARING part. What is the use/goal of this?
    Could you please explain?

    Again thanks!

    Reply
  10. spacer Martin says:
    November 25, 2009 at 3:34 am

    @ Ben

    The sharing drop-box gives you a unique URL to the picture, which, when opened, shows the pic in the lighbox view on page load.

    You can build upon this functionality, by providing a way for users to share the image on twitter, facebook and other social media.

    Reply
  11. spacer Ben says:
    November 25, 2009 at 4:27 am

    OK, Martin.
    It's clear now, thanks.

    Reply
  12. spacer Iliyan says:
    November 25, 2009 at 3:09 pm

    You've done a great job, Martin - there is no doubt. I am waiting eagerly for your next tutorial ;)

    Good luck

    Reply
  13. spacer 206source says:
    November 25, 2009 at 7:06 pm

    holly cheat! very hard work!

    Reply
  14. spacer hellsing says:
    November 26, 2009 at 4:18 pm

    Thank to $god it's free so there is no charge for awesomeness nor for attractiveness ;-)

    I don't know why, but if I copy the 'share' URL, paste into the address line and press enter, nothing happens (I think it should reload the page and zoom the selected image). When I surf to an other webpage and paste the URL again, it works well. I have FF 3.5.5.

    Reply
  15. spacer Michael says:
    November 27, 2009 at 5:45 am

    Wow, this is really a great gallery and the first time I see PHP with jquery etc. :-)

    Reply
  16. spacer Domas says:
    December 2, 2009 at 1:28 pm

    That's the great tutorial,
    I'm currently implementing this for my project, and when I'm opening it with IE8, all the thumbnails are displayed in same way, these are not randomly rotated..

    Is it just for me or its something with IE?

    Reply
  17. spacer Gloria says:
    December 3, 2009 at 7:05 pm

    Great job. Love the look and feel of it. Also, thanks for sharing. This question is probably out of my limited design range, but any tips on how to implement this on the Thesis theme for wordpress? Or just a category page (ex: /category/photography)? Many thanks!

    Reply
  18. spacer Martin says:
    December 5, 2009 at 1:03 am

    @ hellsing

    This happens because the URL is checked only on page load. And because the share URL differs to the default gallery one only by a hash parameter (adding hash parameters to the url does not reload the page), the change becomes unnoticed.

    However if you paste the share URL in the address bar, but haven't yet opened the gallery, the hash is detected and the pic is zoomed on page load.

    This can be fixed (if required) by setting the if statement on lines 79 - 84 of script.js as a interval with setInterval. This will check the URL every second (or few seconds).

    @ Domas

    The gallery uses a number of CSS rules that are yet not supported by IE. However you still have a fully functional gallery (only the images are not rotated, and there are no drop-shadows).

    Reply
  19. spacer tap says:
    December 20, 2009 at 4:06 pm

    it's a fantastic css3 gallery but it doesn't work with i.e. the rotation isn't supported by i.e. and the pictures are displayed horizzontally :((((

    Reply
  20. spacer Johnny says:
    December 25, 2009 at 3:18 am

    Hey, Nice post, I rather like the Gallery.

    Reply
  21. spacer Antonio Ramirez says:
    January 6, 2010 at 3:44 pm

    Amazingly well explained and exposed... loved it... Thanks!

    Reply
  22. spacer gautham says:
    January 13, 2010 at 1:01 pm

    Awesome job. Hats off that you share this work with everyone....

    Reply
  23. spacer Kaj says:
    January 15, 2010 at 4:02 pm

    Thanks for a great tutorial!

    I have one problem though. The images doesn't come up rotated - even the demo you have on this page doesn't show any rotated images.

    Can it be smth wrong with my browser? Have tested in both Firefox and IE

    Reply
  24. spacer
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.