How to Integrate the jQuery Galleria and jCarousel Plugins

There are loads of great jQuery plugins, some more useful than others. The two I’ve recently used quite heavily are Galleria and jCarousel. Both well known for their flexibility and the ease of customization. But what if you’d like to make them work together to build an image gallery?

Simple photo gallery with Galleria and jCarousel

Introduction

and the only solution I came across, and the best example of what we’re going to achieve is Alex Wilson’s gallery. This tutorial is based on similar concept, but with a few improvements.

Let’s get busy and prepare our files structure. We need is a copy of the latest jQuery release (1.3.2 at the time of writing), Galleria 1.0 and jCarousel 0.2.3. Your file structure looks like this:

Files structure

The “photos” folder contains some free photos from sxc.hu.

The Example Page

Have a look at the page we’re going to work on.

Head

1
2
3
4
5
6
7
8
<link rel="stylesheet" type="text/css" href="css/main.css" />
<link rel="stylesheet" type="text/css" href="jcarousel/lib/jquery.jcarousel.css" />
<link rel="stylesheet" type="text/css" href="jcarousel/skins/tango/skin.css" />
 
<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="js/jquery.galleria.min.js"></script>
<script type="text/javascript" src="jcarousel/lib/jquery.jcarousel.pack.js"></script>
<script type="text/javascript" src="js/tutorial.js"></script>

In the head section we add all necessary files, like stylesheets and JavaScript files.

Body

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
<div id="wrapper">
    <h1>Simple photo gallery with Galleria and jCarousel.</h1>
 
    <div id="img"></div>
        <ul id="gallery" class="jcarousel-skin-tango">
            <li><a href="i/photos/fish.jpg" title="Fish 1"><img src="i/thumbs/fish.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/gourami.jpg" title="Dwarf Gourami"><img src="i/thumbs/gourami.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/underwater.jpg" title="Underwater"><img src="i/thumbs/underwater.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/anemone.jpg" title="Anemone fish"><img src="i/thumbs/anemone.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/palms.jpg" title="Palms perspective"><img src="i/thumbs/palms.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/relax.jpg" title="Relax"><img src="i/thumbs/relax.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/sun.jpg" title="Sun and palms"><img src="i/thumbs/sun.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/palms2.jpg" title="Palm trees 2"><img src="i/thumbs/palms2.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/waterfall.jpg" title="Waterfall"><img src="i/thumbs/waterfall.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/beach.jpg" title="The Beach"><img src="i/thumbs/beach.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/sunset.jpg" title="Watching the sunset"><img src="i/thumbs/sunset.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/palms3.jpg" title="Palm trees 3 "><img src="i/thumbs/palms3.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/sunset2.jpg" title="Sunset"><img src="i/thumbs/sunset.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/palms4.jpg" title="Palm trees 4"><img src="i/thumbs/palms4.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/tropical.jpg" title="Tropical waters"><img src="i/thumbs/tropical.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/pineapple.jpg" title="Pineapple"><img src="i/thumbs/pineapple.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/island.jpg" title="Island"><img src="i/thumbs/island.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/flower1.jpg" title="Flower"><img src="i/thumbs/flower1.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/paradise.jpg" title="Paradise beach"><img src="i/thumbs/paradise.jpg" width="100" height="80" alt="" /></a></li>
            <li><a href="i/photos/thatch.jpg" title="Natural Thatch"><img src="i/thumbs/thatch.jpg" width="100" height="80" alt="" /></a></li>
        </ul>
    </div>
</div>

This page consists of only one empty div and an unordered list. Each list item contains a link to a full size image with title attribute (which is going to be a caption) and a thumbnail image. That is actually everything we need to set up our gallery.

CSS

This is a really simple example, so we won’t spend much time styling our gallery. Just set up the dimensions, and add some colors and rounded corners for Gecko and Webkit browsers.

This is complete main.css file:

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/* =Reset
   ----------------------------------------------------*/
 
html, body, div, span, a,
h1, img, ul, li, form {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
background: transparent;}
a { text-decoration: none; }
ul li {list-style: none;}
 
/* --- */
 
body {
    padding: 20px 0;
    font: medium/1.3 Helvetica, Arial, sans-serif;
    color: #222;
    background-color: #fafafa;
}  
 
form { margin-top: 1em; }
 
ul, form ul li { margin-bottom: .5em; }
 
strong { font-weight: bold; }
 
h1 { margin-bottom: 1em; }
 
#wrapper {
    width: 700px;
    margin: 0 auto;
    padding: 20px;
    background-color: #E5EDF2;
}
 
#img {
    position: relative;
    width: 700px;
    height: 450px;
    margin-bottom: 1em;
}
 
#gallery { height: 84px; }
 
#wrapper, #img, #gallery li {
    border: 1px solid #223106;
    -moz-border-radius: 3px;
    -webkit-border-radius: 3px;
}
 
#gallery li {
    float: left;
    padding: 1px;
    background: transparent url(../i/ajax-loader-small.gif) 50% 50% no-repeat;
    border-color: #345;
    cursor: pointer;
}
 
.caption {
    display: block;
    position: absolute;
    bottom: 0;
    left: 0;
    width: 96%;
    height: 50px;
    padding: 0 2%;
    line-height: 50px;
    color: #fff;
    background-color: #000;
    opacity: .8;
}

Setting up the Galleria

Important note: if you’re using an older copy of Galleria there’s one more thing to do.
Your copy might still use the old jQuery attribute selector with “@” to find the rel attribute, which is not supported by jQuery 1.3. To solve this problem open the jquery.galleria.min.js file and use the “find and replace” option in your code editor (e.g. CTRL+H in Notepad++ or CTRL+F in Aptana Studio). You should search for “@rel” and replace it with “rel”. From now on, Galleria and the newest jQuery can work together.

If you download the latest copy now, there’s no need to worry about this issue. It’s been fixed recently.

Using Galleria, like most jQuery plugins, is child’s play. To set up a basic gallery with no special effects, you need just one line of code:

1
    $('#gallery').galleria()

Of course, we’re not satisfied with the result so let’s add some flare. Each part is described in the comments.

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
$('#gallery').galleria({
    // #img is an empty div which holds full size images
    insert: '#img',
 
    // enable history plugin
    history: true,
 
    // function fired when the full size image is displayed
    onImage: function(image, caption, thumb) {
 
        // fade in the image 
        image.hide().fadeIn(500);
 
        // animate active thumbnail's opacity to 1, other list elements to 0.6
        thumb.parent().fadeTo(200, 1).siblings().fadeTo(200, 0.6)
    },
 
    // function similar to onImage, but fired when thumbnail is displayed
    onThumb: function(thumb) {
        var $li = thumb.parent(),
            opacity = $li.is('.active') ? 1 : 0.6;
 
        // hover effects for list elements
        $li.hover(
            function() { $li.fadeTo(200, 1); },
            function() { $li.not('.active').fadeTo(200, opacity); }
        )
    }        
}).find('li:first').addClass('active') // displays first image when Galleria is loaded

The onImage function accepts three arguments:image – current image, caption – image caption (taken from title attribute) and thumb, which is the active thumbnail from the gallery ul.

Setting up jCarousel

Note that in this example I’m using a predefined “Tango” skin, but I changed skin.css a bit. I simply modified some widths and heights, to make it fit my gallery.

To use one of the predefined skins, all you need to do is add “jcarousel-skin-skin_name” class to the gallery unordered list and include the corresponding CSS file.

1
2
3
$('#gallery').jcarousel({
    scroll: 5
})

jCarousel can take wide range of parameters, such as scroll, which is the number of items to scroll by. Check out documentation for more information.

Galleria meets jCarousel

And here begins the fun part. The point is to make jCarousel know when it needs to scroll thumbs. Let’s say we want the active thumb to be in the middle of the list, so every time a user clicks on an image (and calls $.galleria.next() function), jCarousel should scroll and center the active thumbnail. The same happens when you click on any list item.

The great thing is that we can scroll the list from anywhere in our code by calling the carousel.scroll(index) function. Let me show you how it works. First, we need a callback function which will be executed right after the jCarousel initialization.

1
2
3
4
5
6
7
8
$('#gallery').jcarousel({
    scroll: 5,
    initCallback: initCallbackFunction
})
 
function initCallbackFunction(carousel) {
 
};

Before we write our function, there are two important things to do.

List item index

We need to somehow store the index of each list item — so we can tell jCarousel to which thumbnail it should scroll. We can do this in many different ways, e.g. by adding an id or class to each item, using captions, or even numbering images from 1 to n. However, these methods require additional attributes or specific naming conventions. Here, I’ll use the handy jQuery method called “data”, which allows us to add some additional information to an element without needless markup. How to use it? Look at our gallery example:

1
2
3
4
5
6
// to each list item
$('#gallery li').each(function(idx) {
 
    // add data 'index' with value idx+1
    $(this).data('index', (++idx));
});

The “each” function takes a parameter which is the index of the current list item. It starts with 0 and we want to number thumbnails from 1, so we need to increment it (++idx) before passing to the item.

Now we can check each item’s data called ‘index’:

1
2
3
$('#gallery li').each(function() {
    $(this).data('index');
});

If you use Firefox and have the Firebug plugin installed (and I really hope you do), use its console and this line below to check if the “index” data was passed to each item:

1
2
3
$('#gallery li').each(function() {
   console.log($(this).data('index'))
});

Image Change Event

The next step is to make sure that the jCarousel will know exactly when to scroll. We want this to happen when a new image is loaded to our #img container. You can call it “image-loaded” event… and we are actually going to create such an event and trigger it from the onImage function.

1
$('#img').trigger('image-loaded')

This works the same way as with standard events — like click or blur.

And that’s it. Now we can make both plugins work together.

initCallbackFunction

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function initCallbackFunction(carousel) {
 
    // bind "image-loaded" event to the #img container (we trigger it inside onImage function)
    $('#img').bind('image-loaded', function() {
 
        // find "index" data of the active thumbnail
        // and subtract by 2 to center
        var idx =  $('#gallery li.active').data('index') - 2;
 
        // scroll carousel and center the active list item
        carousel.scroll(idx);
        return false;
    });
};

You probably wonder why we subtract two from the active thumbnail index? It’s because we want the current thumbnail to be centered. In our gallery there are only five elements in the visible range of the carousel, so to place the active thumb at 3rd position, we need to scroll the list to the item 2 position. Without this subtraction, the active thumbnail would be the first in the visible range.

That’s All?

Well, it depends. Now is the time to use your imagination and add some more effects and improvements. What can we do? Maybe allow users to watch our photos without that annoying caption? Why not. Just set caption’s height to 0 after the Galleria initialization and define hover states for the caption inside the onImage function. Note that we can use chaining here, there’s no need to look for #img again.

1
2
3
4
5
6
7
8
9
$('#img .caption').css('height', 0)
 
$('#img')
    .trigger('image-loaded')
    .hover(
        // use .stop() to prevent animation queue buildup
        function(){ $('#img .caption').stop().animate({height: 50}, 250) }, 
        function(){ $('#img .caption').stop().animate({height: 0}, 250) }
    );

How about using the keyboard to control the gallery? Great! Here you can use another jQuery plugin if you wish. Let me introduce you to the js-hotkeys plugin. Go to the demo page, and review the source code to learn how easy it can be to handle keystrokes. Then, download the plugin to your js folder and add the script file to gallery.html:

1
<script type="text/javascript" src="js/jquery.hotkeys-0.7.8-packed.js"></script>
1
2
3
4
5
6
7
8
9
10
11
// next image
$(document).bind('keydown', 'right', function (evt){ $.galleria.next(); });
 
//prev image
$(document).bind('keydown', 'left', function (evt){ $.galleria.prev(); });
 
// scoll 5 items to the right
$(document).bind('keydown', 'up', function (evt){ $('.jcarousel-next-horizontal').click();  return false; });
 
// scoll 5 items to the left
$(document).bind('keydown', 'down', function (evt){ $('.jcarousel-prev-horizontal').click();  return false; });

Put these lines at the end of the “initCallbackFunction” function, and you’ll gain full control of the gallery, via the arrow keys. Notice that we need to use “return false” when binding such function to the up and down arrows to prevent the standard behavior – scrolling the whole page up and down.

Even More Options

To be honest, I wanted to end this tutorial here, but thought we would enhance the functionality even more with some additional options. First: let the user decide if the captions are visible or not. Second: a slideshow.

We need a simple form with these options:

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
<form action="" method="post">
    <fieldset>
    <legend>Options</legend>
    <ul>
        <li>
            <input id="show-caption" type="checkbox"/>
            <label for="show-caption">show caption</label>
        </li>
        <li>
            <input id="toggle-slideshow" type="checkbox" />
            <label for="toggle-slideshow">toggle slideshow</label>
        </li>
        <li id="slideshow">
            <select id="slideshow-pause">
                <option value="2">2</option>
                <option value="4">4</option>
                <option value="6" selected="selected">6</option>
                <option value="8">8</option>
                <option value="10">10</option>
                <option value="12">12</option>
                <option value="15">15</option>
                <option value="20">20</option>
            </select>
            <label for="slideshow-pause">slideshow pause (seconds)</label>
        </li>                   
    </ul>
    </fieldset>
</form>

The first thing I need to do is write one line for Firefox exclusively. FF likes to leave checkboxes checked after page refreshes, and that might cause some confusion.

1
$('#toggle-slideshow, #show-caption').removeAttr('checked')

Now, when show-caption checkbox is checked, captions shouldn’t hide anymore:

1
2
3
4
5
6
7
$('#show-caption').change(function(){
    if (this.checked) {
        $('#img .caption').stop().animate({height: 50}, 250)
    } else {
        $('#img .caption').stop().animate({height: 0}, 250)   
    }
})

We need to add one if statement inside our onImage function to check the show-caption’s state:

1
2
3
4
5
6
7
8
9
10
$('#img')
    .trigger('image-loaded')
    .hover(
        function(){ $('#img .caption').stop().animate({height: 50}, 250) },
        function(){ 
            if (!$('#show-caption').is(':checked')) {
                $('#img .caption').stop().animate({height: 0}, 250) 
            }
        }
    );

The second option is a slideshow. If you want to see photos without clicking “next” or using keyboard, check the toggle-slideshow checkbox, choose timeout (or leave default 6 seconds) and enjoy the slideshow. This is based on setting and clearing the slideshow interval.

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
var slideshow,
    slideshowPause =  $('#slideshow-pause').val() 
 
$('#slideshow-pause').change(function(){
    slideshowPause = this.value
 
    // clear interval when timeout has changed
    window.clearInterval(slideshow)
 
    // set new interval with new timeout value
    slideshow = window.setInterval(function(){
        $.galleria.next()
    }, slideshowPause * 1000) // must be set in miliseconds
})
 
$('input#toggle-slideshow').change(function(){
    if (this.checked) {
        $('#slideshow').fadeIn()
 
        // set interval when slideshow is enabled
        slideshow = window.setInterval(function(){
            $.galleria.next()
        }, slideshowPause * 1000)
    } else {
        $('#slideshow').fadeOut()
 
        // clear interval when slideshow is disabled
        window.clearInterval(slideshow)
    }
})
Gallery options

Image Loading Tip

When the page is loading, you may notice that there are empty gaps inside the list elements until the thumbnails are loaded. To indicate that something is loading, we can place a tiny ajax loader image inside each list item.

1
2
3
#gallery li {
    background: transparent url(../i/ajax-loader-small.gif) 50% 50% no-repeat;
}

Moreover, we can enhance this solution with fade-in effect just when each thumb is loaded.

1
2
3
4
5
6
// hide all thumbnails
$('#gallery li img').css('opacity', 0).each(function() {
    // when img is loaded, animate opacity to 1
    if (this.complete || this.readyState == 'complete') { $(this).animate({'opacity': 1}, 300) } 
    else { $(this).load(function() { $(this).animate({'opacity': 1}, 300) }); }
});

You might wonder why I didn’t use jQuery’s load function? — Because a problem with caching images might occur.

To solve this problem, I first check if the image is complete (2 different ways for good browsers and IE6). If it is, we can animate its opacity, otherwise we use the load function (thanks Sopel for the solution).

Image loading effect with ajax-loader

And that’s all for now. Of course you can do much more with these plugins, just review the documentation.

One last tip. When using plugins, remember that they are usually prepared for many different implementations and customization and there is usually much more code than necessary for your project. Always try to delete needless parts before uploading it on your server. E.g. in our example we don’t need styles and images for the vertical carousel, so I erased them. You can even put these styles into your main style sheet to save a few HTTP requests.



27

Comments
  • Really Useful solutions for Gallery and Courcel

  • jamie says:

    funny how something you’re looking to do sometimes just presents itself :)

  • Crysfel says:

    looks very good! thank you :D

  • xmox2k8 says:

    awesome tuts.

    i am just wondering how can i make a clone like on this site http://www.foresceneweb.com/portfolio.html . i would like to clone their portfolio.

    best regards
    xmox

  • Dean says:

    Demo page was sloooooow to appear.

  • SiGa says:

    Very useful and nice – thanks for that one, much appriciated!

  • DJ says:

    There seems to be an error in the demo – I got “## Error loading image: i/photos/palms4.jpg” on one of the thumbnails and the previous thumbnail didn’t match the photo it displayed.

  • Nori Silverrage says:

    Thats cool but… Is there a way to just grab all the pictures in a specific folder? If you have a album that changes relatively often or has a lot of pictures that can be a bit of work.
    The way I currently do it is just name them 1.jpg up to 20.jpg and when I have new images I just replace them. But it’d be nice to have clients for instance, just have to upload pictures to a folder and voila!

  • Matthew Hunt says:

    Thanks for this tutorial, I actually played around with something similar using jflow and jcarousel, there is code to set the jflow plugin to autoslide as well. There is a similar plugin, http://pikachoose.com/demo/ but this pikachoose plugin may not have an automatic sideshow function built in.

  • Thanks for the tutorial, I played arround with it and it worked very well.

    C

  • pvf says:

    Hi!!! thanks for this tutorial!

    works great, as a static page, but how could this be integrated in wordpress? I know theres a galleria plugin but the functionality is limited and the client is looking for this solution, on their wordpress site…

    any ideas?

    any feedback is greatly appreciated :)

    thanks,
    pvf

  • Natalia says:

    Does anyone can help me?

    I’m trying to figure out the way to align image together with a caption…

    I have different width images that align to the centre, however the captions below the images, in my case, have to be aligned to the bottom left corner of the image (different width).

    Is there a way to do it using this specific script?

    Thank you for an amazing gallery and I hope someone can help me out a bit here.

  • Steve says:

    Nice one! Really good examples…will have some fun now.

  • luan says:

    Your demo doesn’t work in IE 6 or 7. Can you do something about that?

  • Thor says:

    Thanks for adding this tutorial. However, the code doesn’t function correctly on my copy of Google Chrome (2.0.172.38).

  • Yes, great tutorial, but yes, shame it doesn’t work properly in IE6, needed this style gallery for a client who uses IE6, damn!!

    Thanks for the tutorial though work well in all decent browsers!

    x x

  • Peter says:

    Thanks for the tutorial.
    Just a question on the loading function. It seems when you click on a thumbnail whose parent image hasnt fully loaded yet, the image opens up in a new window. Is there any way in which to ‘fix’ this. It appears to be quite a problem with slower connections and slightly bigger images.

    Thanks!

  • Derek says:

    Hello, this was a brilliant tutorial, and I’ve even gotten it working on Wordpress pulling from a NextGen Gallery, which is awesome…

    Except whenever I try the keystrokes, it loads the next image, then immediately bounces back to the previous. Does anyone know what might be causing that behavior? Right now I’m stumped.

  • Ed Oby says:

    How can I have two galleries on one page. I’ve tried and tried and no luck can someone tell me how to have more than one on a page. Want to use for projects with lots of images per project and multiple project on a page.

  • vestige says:

    Thanks heaps for the tutorial – it’s been the only one I could follow so far!!

    I have a few problems that I was hoping someone here can please help me with:

    - How can I make the bg of the thumbnail frame black?

    - Is it possible to position the scrollbar underneath the main image? (ie. leave a gap between the main image and the thumbnails)

    - The ajax loading gif doesn’t come up when loading (some images wont load so it’s just a black space)

    - Is it possible to change the arrows to a different style/color? (I can’t open up the file in photoshop)

    I also can’t seem to set the page background to my own bg image..

    Thanks heaps in advance!!!

  • Vestige says:

    Hi there,

    I’m not sure if anyone can please help me with this..

    How do I set a background image to the page? (There are so many files, I’m not sure which to modify?)

    Thanks in advance!!! =)

  • Vestige says:

    Update- I’ve worked out how to change the thumbnail container to black.. but now the left and right arrows don’t show up~~!

  • ginita says:

    Thank you for your tutorial.

    I would like to integrate galleria with vertical carousel. So far, it doesn’t work. I’m getting confused with loads of css files which probably interfere with each other. Please can you direct me to the way of making a similar thing with vertical carousel?
    Thanks in advance.

  • Michael Doni says:

    Hi,

    Very nice and usefully!!!!!!!!!!!

    Thanks for a great and amazing jog, I’ll try to integrate this on my next websiste, and keep the credits from you.

    As you know, This Galerry and another effects, like this, are so nice to put in websites
    =]

    Regards,

    Michael Doni
    Technology – Share – And Knowledge

  • ginita says:

    The issue in my previous post is solved. At least for Firefox and Safari. I cannot get these two plugins to work in IE6 and 7. Your demo does work. I wonder where the problem lies – in css or js? And can anyone share insights on what has to be done to get things working in IE?

  • Kait says:

    I’m working on a site and used this amazing fusion.

    Just a few questions:

    1. Is there a way to make the slideshow play when first loaded, instead of asking the user?
    2. Same thing with the caption– I’d like to have it always show
    3. How can I achieve this stuff, and also remove the options

    –essentially, I want to have an auto play, always visible captioned slideshow with thumbnails. Is this possible?

    Thank you SOOO MUCH!

  • Zully says:

    Nice tutorial, easy to follow.

    Can someone shed some light on how can I make the main image border smaller to fit small images (400 by 300px).

    Same applies to thumbnails to make the border small to fit thumbnail 50 by 50px;
    Thanks