How to - Fading image gallery with JQuery

filed under javascript

Update 2013-04-02: This code is really gross and embarrassing. I'm only keeping it here for historical purposes. Please use this only as a reference. If you're really stuck for a simple galery, check out the Bootstrap Project's Carousel.

Today I threw together a javascript gallery that fades between images automatically, between images. First, here's how to layout the gallery you want to display:

HTML

<div id="gallery-container">
   <div id="gallery">
      <ul>
         <li id="panel-1">
            <img src="image1.jpg" alt="" />
         </li>
         <li id="panel-2">
            <img src="image2.jpg" alt="" />
         </li>
         <li id="panel-3">
            <img src="image3.jpg" alt="" />
         </li>
      </ul>
   </div>
</div>

The HTML is pretty self explanatory, so I won't explain it.

Javascript (requires JQuery)

 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
var fader = (function () {
    var fader, faderContainer, fadeTo;

    var init = function() {
       faderContainer = $('#gallery-container');
       fader = $('#gallery');

       fadeTo = $('<ol/>', { id: 'gallery-jump-to' }).appendTo(faderContainer);

       var current = window.location.hash || '#panel-1';

       fader.find('ul li').first().addClass('active');

       fader.find('ul li').each(function(i) {

          var href = '#panel-' + (i + 1);
          var button = $('<li><a href="' + href + '">&bull;</a></li>').appendTo(fadeTo);

          if (href === current) {
             button.addClass('active');
          }

          button.find('a').click(function(event) {
             event.preventDefault();

             var link = $(this);
             var id = link[0].hash;

             $(id).parent().children('li').each(function(i) {
                var elem = $(this);

                if (elem.hasClass('active')) {
                   var active = elem;
                   var next = active.next();

                   if (active.is(':last-child')) {
                      next = $(id).parent().children('li').first();
                   }

                   // hide the active image, then fade in the next one
                   active.fadeOut(800, function() {
                      active.removeClass('active');
                      next.addClass('active');

                      next.fadeIn(800);
                      next.show();
                   });
                } else {
                   $(this).hide(); // hide the rest of them so the active one is visible
                }

                // change the buttons
                link.parents('li').siblings().removeClass('active');
                link.parent().addClass('active');
             });

          });
       });

       setInterval(nextSlide, 5000);
    };

    var nextSlide = function() {
       var active = fadeTo.find('li.active');

       if (active.is(':last-child')) {
          fadeTo.find('li:first-child a').click();
       } else {
          active.next().find('a').click();
       }
    };

    $(init);
})();

I'll explain this in terms of the functions.

fader (entire script):

This is the "object" that results from a gallery. You don't really need to handle this or use it at all, it's just there to group things together a bit.

init (lines 4-61):

This does a few things, but overall, it initalises the gallery. More specifically:

  • Adds buttons to the end of gallery-container so users can select an image to view
  • Sets the first image to active
  • For each of the buttons that were added, upon clicking, fade out the active image, and fade in the next one. If the active image is the last one in the list, fade in the first image.

nextSlide (lines 63-71):

This method does nothing but call the click method for the next link, as described up above. Essentially, this is what changes the image.

Finally, you may want to style your gallery, as I'm sure the default would look pretty ugly. Here's something decent:

#gallery-container {
   height: 350px;
   position: relative;
   margin-bottom: 10px;
   -moz-box-shadow: 0 5px 5px #666;
   -webkit-box-shadow: 10px 10px 5px #888;
   box-shadow: 10px 10px 5px #888;
   border: 1px solid #fff;
   background: #fff;
}

#gallery {
   width: 100%;
   height: 350px;
   position: absolute;
   overflow: auto;
}

.javascript #gallery {
   overflow: hidden;
}

#gallery ul {
   overflow: hidden;
}

#gallery ul li {
   width: 960px;
   height: 360px;
   padding-top: 1px;
   margin-top: -1px;
}

.javascript #gallery ul li {
   display: inline;
   float: left;
}

.javascript #gallery ul li:first-child {
   margin-left: 0;
}

#gallery-jump-to {
   position: absolute;
   bottom: 15px;
   right: 30px;
   font-size: 40px;
}

#gallery-jump-to li {
   display: inline;
}

#gallery-jump-to li a {
   text-decoration: none;
   color: #f90;
   *line-height: 0.5em;
   text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
}

#gallery-jump-to li.active a {
   color: #45cd3b;
}

I'm not going to run you through how to customise the styling as this post is already HUGE. If anyone desperately needs help styling things, just post a comment.

Conclusion

It's worth noting that line 60 sets the images to change automatically every 5 seconds, using the setInterval command. If you want to change the fading to another effect, lines 41 and 45 are what you're looking for. Also, if I had used the effects that come with JQuery UI (one of the best libraries on Earth) instead of the fadeIn() and fadeOut() functions that JQuery ships with, I'm sure the script would be shorter and way more maintainable.

Related Posts