Stylish photo gallery using jQuery, jCarousel and Galleria

The technique we are going to discuss isn’t groundbreaking and it certainly isn’t new. What we hope to achieve with this post is to show how simple it is to create a stylish but simple photo gallery with jQuery. There are no bells and whistles on this one, but the two jQuery plugins we use can be taken a lot further and both bells and whistles can be added with ease. We like making things simple here at Grow Media, it means we can spend less time at the computer and more time outside!!

The photo gallery we discuss in this post is something we used on a recent site we built. You can see the gallery in action at – dianathorneycroft.com. The portfolio pages all use it. Before we dive into the code lets look at the goals we needed to achieve for the gallery.

The gallery needed to be:

  1. simple! (this should always be the case)
  2. easily expandable (doesn’t matter how many photos per gallery)
  3. easily editable (animation times etc.)
  4. jQuery based (only because jQuery is library of choice not because it is better than any other)
  5. able to display captions on the photos

Doing the usual pre-project research to try and fulfill these goals I came across Galleria. This was perfect for our needs. It made use of some simple transitions. It wasn’t too fancy and it looked as though it was going to be easy to edit. The one problem Galleria seemed to have was that the thumbnails didn’t scroll. If you added more they simply appeared as rows of thumbnails. So we needed a carousel style plugin for jQuery. After doing some searching I came across a post on Lost in the Woods (themeforest blog) that explained how to use Galleria with jCarousel. PERFECT!!

I had used jCarousel before but I had always used it on its own. As it turns out it works very well with Galleria to provide just what we were looking for. All we use jCarousel for is to scroll the thumbnails. Galleria does all the heavy lifting with the loading of images and creation of thumbnails.

Before looking at the code we used to make Galleria and jCarousel talk to each other it is a wise idea to grab the main JavaScript files. The first is jQuery, second is Galleria and third is jCarousel. When you download jCarousel it comes with a lot of extra bii’ness that isn’t needed if you want to follow along with this post. All you need is the jquery.jcarousel.pack.js file.

So enough babble, time for the code:

Lets start with the HTML:

1
2
3
4
5
6
7
8
9
10
11
12
<div id=”img”></div>
<ul id=”gallery” class=”jcarousel-skin”>
<li><a href=”image01.jpg” title=”Caption 01″><img src=”thumb01.jpg” width=”100″ height=”80″ alt=”” /></a></li>
<li><a href=”image02.jpg” title=”Caption 02″><img src=”thumb02.jpg” width=”100″ height=”80″ alt=”” /></a></li>
<li><a href=”image03.jpg” title=”Caption 03″><img src=”thumb03.jpg” width=”100″ height=”80″ alt=”” /></a></li>
<li><a href=”image04.jpg” title=”Caption 04″><img src=”thumb04.jpg” width=”100″ height=”80″ alt=”” /></a></li>
<li><a href=”image05.jpg” title=”Caption 05″><img src=”thumb05.jpg” width=”100″ height=”80″ alt=”” /></a></li>
<li><a href=”image06.jpg” title=”Caption 06″><img src=”thumb06.jpg” width=”100″ height=”80″ alt=”” /></a></li>
<li><a href=”image07.jpg” title=”Caption 07″><img src=”thumb07.jpg” width=”100″ height=”80″ alt=”” /></a></li>
<li><a href=”image08.jpg” title=”Caption 08″><img src=”thumb08.jpg” width=”100″ height=”80″ alt=”” /></a></li>
<!–You can add as many images as you want here–>
</ul>

The great thing about this gallery is that it is just an unordered list. This makes it very handy to implement with a content management system. The next piece of code I want to show is the JavaScript. This is slightly out of order as the CSS should really come next but I am not going to complicate things with the CSS until the end.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$(document).ready(function(){
$(‘#gallery li’).each(function(idx) {
$(this).data(‘index’, (++idx));
});
$(‘#gallery’).jcarousel({
animation: 1000,
buttonNextHTML: ‘<a href=”#” onclick=”$.galleria.next(); return false;”>next �</a>’,
buttonPrevHTML: ‘<a href=”#” onclick=”$.galleria.prev(); return false;”>prev �</a>’,
wrap: ‘both’,
initCallback: initCallbackFunction
});
function initCallbackFunction(carousel) {
$(‘#img’).bind(‘image-loaded’,function() {
var idx =  $(‘#gallery li.active’).data(‘index’) – 3;
carousel.scroll(idx);
return false;
});
};
$(‘#gallery li img’).css(‘opacity’, 0).each(function() {
if (this.complete || this.readyState == ‘complete’) { $(this).animate({‘opacity’: 1}, 300) }
else { $(this).load(function() { $(this).animate({‘opacity’: 1}, 300) }); }
});
$(‘#gallery’).galleria({
insert: ‘#img’,
clickNext: true,
history: false,
onImage: function(image, caption, thumb) {
image.hide().fadeIn(1000);
thumb.parent().fadeTo(600, 1).siblings().fadeTo(600, 0.4);
image.attr(‘title’,’Next image »’);
$(‘#img’).trigger(‘image-loaded’);
},
onThumb: function(thumb) {
var $li = thumb.parent();
$li.hover(function(){$li.fadeTo(200, 1);},function(){$li.not(‘.active’).fadeTo(200, 0.4);})
}
}).find(‘li:first’).addClass(‘active’);
});

Now it’s time for some explanation. Starting from line 1 we use the standard jQuery document ready function. This needs little explanation aside from the fact it lets the entire DOM load before doing anything within its bounds. Moving on to line 2:

$(‘#gallery li’).each(function(idx) {
$(this).data(‘index’, (++idx));
});

Here we apply an index number to each of our list items. This makes it possible to know which thumbnail is active and therefore where we need to scroll to. If you look at the generated code inside a debugger such as firebug you will see jCarousel has added a jcarouselindex property to each <li> element. Onto line 5:

$(‘#gallery’).jcarousel({
animation: 1000,
buttonNextHTML: ‘<a href=”#” onclick=”$.galleria.next(); return false;”>next �</a>’,
buttonPrevHTML: ‘<a href=”#” onclick=”$.galleria.prev(); return false;”>prev �</a>’,
wrap: ‘both’,
initCallback: initCallbackFunction
});

This section of code initiates jCarousel on the div with an id of gallery. The code that sits inside this instantiation is simply building jCarousel with certain options. Starting with the animation property we can tell jCarousel how long to take when scrolling. This is set in milliseconds.

buttonNextHTML: ‘<a href=”#” onclick=”$.galleria.next(); return false;”>next �</a>’,
buttonPrevHTML: ‘<a href=”#” onclick=”$.galleria.prev(); return false;”>prev �</a>’,

The next two lines remove the default next and previous buttons and replace them with the HTML we want to use instead. By default, jCarousel generates two divs at either end of the thumbnail list. These divs contain next and previous buttons that actually move only the thumbnail bar rather than the main image. What we wanted was for the large image to move to the next or previous image at the same time as the thumbnail image. So to do this we used a function that comes as default in the Galleria code ($.galleria.next(); -  $.galleria.prev();) and let jCarousel replace its default next and previous button. The best way to see the difference between our gallery navigation and the default jCarousel gallery navigation is by looking on the Lost in the Woods site.

The next bit of code wraps the carousel. If you are on the first image and press previous it will animate to the last thumbnail in the list and vice versa if you are on the last thumbnail of the list.

wrap: ‘both’,

Our final piece of code is to initiate a callback function. You can do anything with this callback function but in our case we are using it in the next block of code to check which image is displaying. Once we have done this we can animate the thumbnails forward or backwards to keep the active thumbnail central in the thumbnail navigator. As a side note if you check out the jCarousel documentation there are lots of other options you can use to personalize your carousel.

initCallback: initCallbackFunction

Onto line 12 and our callback function.

function initCallbackFunction(carousel) {
$(‘#img’).bind(‘image-loaded’,function() {
var idx =  $(‘#gallery li.active’).data(‘index’) – 3;
carousel.scroll(idx);
return false;
});
};

Our callback function finds out which index we are on and then makes sure there are 3 indexes in front of it that are being shown in the thumbnail navigator. We can change the number of thumbnails that need to be in front of the active thumbnail by changing the number 3 to anything we want. In our case we wanted seven thumbnails to be visible in the thumbnail navigator so using the number 3 makes the active thumbnail center of the thumbnail navigator.

The block of code at line 19 is where we start playing with opacity:

$(‘#gallery li img’).css(‘opacity’, 0).each(function() {
if (this.complete || this.readyState == ‘complete’) { $(this).animate({‘opacity’: 1}, 300) }
else { $(this).load(function() { $(this).animate({‘opacity’: 1}, 300) }); }
});

This little block of code is best described by quoting Lost in the Woods:

[we didn’t use jQuery’s load function] because a problem with caching images might occur. To solve this problem, [we] first check if the image [load] is complete (2 different ways for good browsers and [for] IE6). If it is, we can animate its opacity, otherwise we use the load function…

You can change the values for the animation and make it fade faster or slower.

The final code block at line 23 is where we apply the Galleria plugin to the images and play with effects.

$(‘#gallery’).galleria({
insert: ‘#img’,
clickNext: true,
history: false,
onImage: function(image, caption, thumb) {
image.hide().fadeIn(1000);
thumb.parent().fadeTo(600, 1).siblings().fadeTo(600, 0.4);
image.attr(‘title’,’Next image »’);
$(‘#img’).trigger(‘image-loaded’);
},
onThumb: function(thumb) {
var $li = thumb.parent();
$li.hover(function(){$li.fadeTo(200, 1);},function(){$li.not(‘.active’).fadeTo(200, 0.4);})
}
}).find(‘li:first’).addClass(‘active’);

Galleria has many different options just as jCarousel did. We are playing with a few of the key options to customize the functionality and display of our photo gallery. The first option we use is insert. Here we tell Galleria where to place the large image. In our case we used the default div id of img. You can see this in the HTML block shown previously in the post. The next option is clickNext. This is so that when the user clicks on the main image it moves them to the next image.

We deactivated the next option – history. It seemed to be a great idea in principle but didn’t work as well in practice. The option allows users to be able to view each image as a specific URL which means that they can add them as bookmarks and navigate the gallery using the browser forward and back button. The problem I found with this is that unless the images were in the same folder as the gallery HTML page the URLs would quickly become ugly and long. Of course we could have played with redirects and url re-writes but we like to go out and enjoy ourselves!! Added to the fact I think users prefer to navigate photo galleries with the navigation provided rather than with their back and forward buttons.

The next option is onImage:

onImage: function(image, caption, thumb) {
image.hide().fadeIn(1000);
thumb.parent().fadeTo(600, 1).siblings().fadeTo(600, 0.4);
image.attr(‘title’,’Next image »’);
$(‘#img’).trigger(‘image-loaded’);
},

This is the how we play with the fading in and out of thumbnails when the main image is loaded. The first line in the onImage option is – image.hide().fadeIn(1000); – with this line of code we simply hide the main image and then fade it in to 100% opacity in 1000 milliseconds (1 second).

Our next line – thumb.parent().fadeTo(600, 1).siblings().fadeTo(600, 0.4); – is to play with the thumbnail opacity. We are making the active thumbnail 100% and making all the other thumbnails 40% or 0.4. Each of these animations occurs in 600 milliseconds. I really like this part of the plugin as it makes use of the jQuery selectors extremely well with .parent and .siblings.

The next line – image.attr('title','Next image »'); – is to add a title attribute to the main image that says “Next image »”. Depending on the browser this creates a “tooltip” when the user hovers over the image. It helps users know that they can click on the main image to navigate the gallery.

The final line – $('#img').trigger('image-loaded'); – intiates the image-loaded function that we bound to the img div on line 13. This was the function that made the active thumbnail central in the thumbnail navigator.

Nearly at the end now – just one more option in the Galleria plugin:

onThumb: function(thumb) {
var $li = thumb.parent();
$li.hover(function(){$li.fadeTo(200, 1);},function(){$li.not(‘.active’).fadeTo(200, 0.4);})
}

This piece of code fades our thumbnails from 0.4 to 1 when you hover on them and then back to 0.4 when your mouse moves off them. We do one check in the hover function and that is to find out if the thumbnail is the active thumbnail. If it is then we don’t want to fade it to 0.4 it needs to stay at 1.

Onto the final piece of code:

.find(‘li:first’).addClass(‘active’);

This piece of code is attached to the Galleria instantiation using the jQuery dot syntax. All it does is find the first <li> in the gallery div and add a class of active. This simply means that when the page is first loaded the first thumbnail will be at 100% opacity and the main image will be the larger version of the thumbnail. You can use any id or class in the .find() we just decided that we wanted people to start at the beginning of the gallery when they first landed on the page.

There you have it – a simple but stylish photo gallery using jQuery, jCarousel and Galleria. As the disclaimers have stated all the way through the post, both the Galleria plugin and jCarousel plugin can be used in much more complicated and customized ways. They both have a lot to offer on their own and together. I am also sure that there is a very good MooTools plugin that does exactly the same thing. But we like jQuery and for now that is our library of choice.

Just as a final part of the post I want to share the CSS that we used for our gallery. I am not going to go through it but if you have any questions then please let me know in the comments. I am also going to provide the HTML file for your reference. This is just so you can “view source” then copy and paste it.

As usual we would love to hear if you thought this post was useful and also if you have any additions to the code that you think might make it better.

Thank you for reading.