Search

Slider Gallery

Posted on 18th February 2008 — Michiel Kenis requested a tutorial explaining how to create a similar effect used to showcase the products on the Apple web site.

This ‘product slider’ is similar to a straight forward gallery, except that there is a slider to navigate the items, i.e. the bit the user controls to view the items. Simple stuff.

jQuery already has the plugins to create these effects so we don’t have to go about creating them ourselves from scratch.

How to Solve the Problem

To create the slider controlled gallery, we need the following:

  1. Markup that allows us to place several items within a list, and that overflows out of sight.
  2. A slider widget to control what subsection of products we can see.
  3. Logic to translate the sliders position to slide the products inversely (i.e. we slide left-to-right, the products go right-to-left).

I’ve provided a screencast to walk through how create this functionality. Details on how and what I used can be found below.

Watch the slider gallery screencast (alternative flash version)

View the demo and source code used in the screencast

jQuery UI

jQuery UI is “a set of themable widgets and interactions”. For this task, we don’t need much of jQuery UI, but for the UI slider widget, we’ll need the following:

  • jquery.dimensions.js
  • ui.mouse.js
  • ui.slider.js

Of course we’ll still need the latest jquery.js.

All the above scripts can be extracted from the jQuery UI download.

HTML Markup

The markup for the example is straight forward. It boils down to a ul holding the items you want in the gallery, and a div with another nested div, for the slider and it’s handle.

<div class="sliderGallery">
  <ul class="items">
    <li>Item one</li>
    <li>Item two</li>
    <li>Item three, etc...</li>
  </ul>
  <div class="slider">
    <!-- the handler to action the slide -->
    <div class="handle"></div>
    <!-- labels appear against the slider, as pointers to the user -->
    <span class="slider-lb1">slider label 1</span>
    <span class="slider-lb2">slider label 2</span>
    <span class="slider-lb3">slider label 3</span>
  </div>
</div>

CSS

One key feature about the CSS used: in my example, I assumed that I would not have a predefined width to the ul element. As such, I can’t float the li elements and have set widths. To ensure everything flows horizontally, I make use of white-space: nowrap.

I’ve only included the required CSS to create the sliding gallery effect. If you want to see the complete CSS used in the screencast just view the source for the demo

Slider Gallery Container

The overflow ensures the items are hidden, and the position: relative is used to absolutely position the ul element within it.

.sliderGallery {
    overflow: hidden;
    position: relative;
    padding: 10px;
    height: 160px;
    width: 960px;
}

Slider Gallery Items

The white-space: nowrap is what allows us to work with an unknown width in the ul element.

.sliderGallery UL {
    position: absolute;
    list-style: none;
    overflow: none;
    white-space: nowrap;
    padding: 0;
    margin: 0;
}

.sliderGallery UL LI {
    display: inline;
}

Slider Handle

In the screencast, the example uses a background image for the slider handle, and in particular from the example, the width of the handle is larger than the image to allow it to overlay on the left and right arrows.

.handle {
    position: absolute;
    cursor: move;
    top: 0;
    z-index: 100;
    /* bespoke to your own solution */
    height: 17px;
    width: 181px;
}

jQuery

As stated above, we will need to include a series of plugins from the jQuery UI download, then we will add our dash of jQuery to create the sliding gallery effect.

Required Plugins

<script src="jquery.js" type="text/javascript"></script>
  
<script src="jquery.dimensions.js" type="text/javascript"></script>
<script src="ui.mouse.js" type="text/javascript"></script>
<script src="ui.slider.js" type="text/javascript"></script>

Slider Code

$(function () { // see note below
$(window).ready(function () {
  $('div.sliderGallery').each(function () {
    var ul = $('ul', this);
    var productWidth = ul.innerWidth() - $(this).outerWidth();

    var slider = $('.slider', this).slider({ 
      handle: '.handle',
      minValue: 0, 
      maxValue: productWidth, 
      slide: function (ev, ui) {
        ul.css('left', '-' + ui.value + 'px');
      }, 
      stop: function (ev, ui) {
        ul.animate({ 'left' : '-' + ui.value + 'px' }, 500, 'linear');
      }
    });
  });
});

Please note during the screencast I used $(function () {}) - but I’ve had to since change this to $(window).ready. This is because I’m using white-space: nowrap and the width isn’t calculated until after the images are loaded. jQuery’s document ready function fires before the images are loaded - to allow the JavaScript access to the DOM as early as possible.

This wasn’t a problem in the demo because the images were loaded from a local server, and thus loaded fast enough to allow the code to work out the width correctly.

The code breaks down as follows:

window.onload = function () {

When the DOM and images are ready (note that if you don’t use white-space: nowrap then you should use the standard $(document).ready() method).

$('div.sliderGallery').each(function () {

Loop through all the div.sliderGallery elements. This code design sets us up to convert our code to a reusable plugin.

var ul = $('ul', this);

Search for the ul in the context of this - which is currently a div.sliderGallery.

var productWidth = ul.innerWidth() - $(this).outerWidth();

.innerWidth() and .outerWidth() come from jquery.dimensions.js. We’re subtracting the current div.sliderGallery width because when we slide, we want it to stop once the last item is visible, rather than sliding it all the way left until it’s out of sight.

var slider = $('.slider', this).slider({ 

.slider() comes from ui.slider.js.

handle: '.handle',

The class of our slider handle.

slide: function (ev, ui) {
  ul.css('left', '-' + ui.value + 'px');
},

As the handle is moved, we move the ul of items, note that it moves negatively, creating the scrolling effect.

stop: function (ev, ui) {
  ul.animate({ 'left' : '-' + ui.value + 'px' }, 500, 'linear');
}

We use this for when slider area has been clicked, to create the scroll effect.

Taking it Further

When I have a working version of the code, I often try to think how the interaction could be better. Here’s a list of ways it could be improved, in no particular order - if you fancy a challenge:

  1. Better scrolling effect, in particular, fast scroll for the bulk of the animation, and slows down when it’s settling on the final item.
  2. Turn it in to a plugin.
  3. The arrow can be turned in to handlers to slide the handle only part of the distance, rather than all.
  4. A nice effect the Apple version has, is the jump labels, within the slider element, change class given the distance they are from the slider handle. They appear brighter as they’re closer and duller as they are further away from the handle.
  5. Anything else you can think of!

Related screencasts

Demo

If you find this demo doesn't work as expected, it's possibly due to the demo running from within an iframe. Try running the demo in it's own window.

Source Code

Comments

  1. Remy On 23rd July 2009 at 14:07

    Just to say, I’ve been working on fixing this.

    What’s happened is the ‘handle’ property was ditched in the latest version of the jQuery UI, so I’ve been working on a new version that uses all this code with adjustments to make it work using the same handle we used in the demo.

    I’ve got two solutions, but they’re not perfect, once they are - I’ll be posting it up here. So sit tight everyone ;-)

  2. Thomas Meyer On 27th July 2009 at 17:07

    Hi,

    i build a slider with this tutorial, it is NOT working with actual jquery ui.slider.js (1.7.2), plz use the version of the tutorial 1.5.2!

    greetings from lake constanz

  3. iamkeir On 28th July 2009 at 17:07

    Hi Remy - super work on the slider, it’s great and very much appreciated. I am of course wondering if you’d made any headway with solving the problems in newer versions of JQuery yet, as mentioned in your post on 23rd July?

    Best wishes, iamkeir

  4. Elena On 1st August 2009 at 03:08

    Remy,

    I’ve tried some of the other commenter’s suggestions for making a vertical slider but it hasn’t worked. Can you please help????

    Elena

  5. Moritz On 9th August 2009 at 15:08

    Did you try the option “orientation”? Here is an example: http://jqueryui.com/demos/slider/#slider-vertical

  6. Alex Martens On 10th August 2009 at 02:08

    Ok, here is my attempt to adapt the slider for JQuery UI 1.7.2:

    http://dev.levelfivesolutions.net/static/slider/slider-gallery.html

    Besides the obvious, it appears that the horizontal center of the handle needs to always be aligned with the value of the slider (ie ui.value). Therefore, half of the handle will always hang off either side of the slider, otherwise, it will act quirky. Maybe this was obvious to everyone but me. Going into it, this is not how I expected the thing to work.

    To accommodate this and to adapt it to work with the given design, I wrapped the slider in a div and moved the background image there. I gave the handle a negative left margin half the width of the handle. On either side of the wrapped slider I left enough room to accommodate the overhanging handle. Anyway, look at the source… Let me know if you can improve on this in anyway, but I think that this is a pretty straightforward way to do it.

    Good luck! Hopefully all the time I spent figuring this out will save others some time doing so.

    Alex Martens Level Five Solutions

  7. Aaron On 12th August 2009 at 02:08

    Any way to have more than one slider working independently on the same page?

  8. chromax On 14th August 2009 at 18:08

    doesn´t work with the newest jquery, only with “jquery-1.2.6.js”

  9. chromax On 14th August 2009 at 22:08

    all others like the one from wellman has no easing! there not so nice…

  10. Moritz On 15th August 2009 at 12:08

    Yes, there is an possibility to have more than one slider: http://jqueryui.com/demos/slider/#multiple-vertical

  11. Richard Wegner On 17th August 2009 at 05:08

    Hi,

    I have implemented the slider gallery on this page of my client’s web site and they are very happy with the result.

    The only request is whether the scroll could be slowed down when you click on the left or right arrows, instead of jumping immediately to the left or right. I noticed a couple of similar requests here back in April and was wondering if it is possible to change any of the code to make this happen.

    Thanks, Richard

  12. Aaron On 17th August 2009 at 22:08

    Sweet got multiple sliders working with multiple galleries… but there’s an issue with IE7 where the slider bar shows on the top instead of bottom and it cuts off the last image on the end. Any recommendations for a fix?

  13. Moritz On 6th September 2009 at 08:09

    Could you give us a link to the site where you have got the problem? It would make it easier for us to help you ;) Btw: I translated my tutorial for an image slider with the latest jQuery files into English. Maybe it could help with some of the posted problems…

  14. JT On 8th September 2009 at 15:09

    Hi,

    How do I control the position of where the scroll goes? I can move the labels via css, but if I click on say the 3 label I might want it to go “left: 500px; ” I can’t seem to figure this out. When I click on the middle labels it just scrolls to the middle of the list, not to a specific position.

    Thanks - J.

  15. MyWebmasterTips On 28th September 2009 at 04:09

    I’m really impressed with this slider jQuery plugin. Will use it on my sites in the future.

    I’m still kind of new to jQuery, so I’m trying to figure it all out in terms of adding it to Wordpress.

  16. Anton On 28th September 2009 at 08:09

    Hi! I have made a slider like u describe in ur tutorial, but in Safari and Chrome it moves to wrong way. U can chek it there: http://keyprint.ru. I don’t understand why, maybe u can help me? Thanks. :)

  17. JSD On 6th October 2009 at 18:10

    I was having problems getting this to work in jQuery 1.3.2 till I found this: http://www.switchonthecode.com/tutorials/using-jquery-slider-to-scroll-a-div

    could this howto be updated to jQuery 1.3.2?

    the biggest problem with the new version of jQuery is that the “handle” option for the slider was removed..

  18. Harold Maduro On 11th October 2009 at 04:10

    Hi Michiel, just to let you know that JQuery removed the handle: method from the component, you can see it here:

    http://jqueryui.pbworks.com/Slider

    So I guess, we have to style this link as the handler:

    Right?

  19. Harold Maduro On 12th October 2009 at 21:10

    Hi, i have a problem: when i click the slider (not dragging the handler), the slider slides nicely with an animation; but only if I add this line to the code:

    stop: function (event, ui) { elScroll.animate({’left’: (ui.value * -1) +’px’}, 600, ‘easeInSine’); }

    Without adding any ’slide:’ code.

    When i add any of these variations of the slide code, the transition doesn’t works when i click the slider; the handler jumps to it’s destination without any animation.

    slide: function (event, ui) { elScroll.css(’left’, (ui.value * -1) +’px’); }, or slide: function (event, ui) { elScroll.animate({’left’ : (ui.value * -1) +’px’}, 1, ‘jswing’); } or slide: function (event, ui) { elScroll.animate({’left’: -ui.value + ‘px’}, 1); }

    I’m using the latest jquery and jqueryUI. Is there a solution for this?

  20. Harold Maduro On 13th October 2009 at 21:10

    Hi, sorry for spamming the comments, but i wanted to share an addition:

    I managed to code the arrow buttons to scroll incrementally to the left or right.

    First, this is the HTML I use for the Slider:

    I’m using Alex Martens’s solution to the handler constraint problem. I also added two spans, one for each button and having their own background image representing the buttons. The background image for the whole slider is applied to #slider-wrapper.

    Second, the CSS for these guys:

    .slider-wrapper span.left { float: left; background-image: url(../images/background-slider-left.gif); background-position: top left; cursor: pointer; }

    .slider-wrapper span.right { margin-top: -16px; float: right; background-image: url(../images/background-slider-right.gif); background-position: top right; cursor: pointer; }

    And last, the JQuery code (it’s under Document.Ready):

    $("span.left").click(function(){
    
           var elValue = $("your selector span.left").slider('option', 'value');
    
           if(elValue > 0) {
    
              elValue = elValue - 100; // you can change the increment to whatever you like (250, 300, etc).
    
              if(elValue < 0) {
                 elValue = 0;  // so it stops scrolling after reaching the end.
              }
    
              $("your selector .slider").slider('value', elValue); // so the handler jumps to the desired position
              $("your selector ul").animate({'left' : elValue * -1}, 500); // scroll the page
    
           }
    
    });
    

    For the right button, it’s the same, but changing the values it’s supposed to add:

    $(”span.right”).click(function(){

           var elValue = $("your selector span. right").slider('option', 'value');
    
           if(elValue < itemsWidth) {  // i have a variable called itemsWidth, with the max: size of my slider div.  You can change it to whatever is the size of your DIV.
    
              elValue = elValue + 100; 
    
              if(elValue > itemsWidth) {
                 elValue = itemsWidth;  // 
              }
    
              $("your selector .slider").slider('value', elValue); 
              $("your selector ul").animate({'left' : elValue * -1}, 500);
    
           }
    
    });
    

    Hope you find this useful.

  21. Lisa Valdemar On 14th October 2009 at 16:10

    A nice post, thanx. I love the product slider, it has a really nice, modern touch to it. However, I think that the image could be a bit sharper, it is after all 2009. :) Great blog!

  22. d On 29th October 2009 at 09:10

    hiya, any idea how one can get the slider in the right position for IE7 & IE6 ?

  23. Tonny Xu On 4th November 2009 at 04:11

    Great! Very useful post!

    I never thought we can implement such a cool effects in such few lines! You did a great job!

    Thanks.

    Tonny

  24. Alex Mortensen On 6th November 2009 at 10:11

    Hi Remy!! I love your blog! Truly amazing work on the slider, it’s great and very much appreciated. We need more people like you.

    I successfully reverse engineer it to make it work for my project. I am really not sure why people have problems with this? Everything is explained well and in my system it is working flawless on all latest browser’s. I am not trying to look like smart i am just surprised that people have compatibility issues.

    However i am struggling with one simple thing which is not explained in this tutorial. For example/scenario:

    1. On your site you have vertical/horizontal/whatever Main Menu above your slider gallery.
    2. In that same Main Menu you have links named same as in slider gallery (Wi-Fi, Macs, Applications, Servers)
    3. How can i add functionality in a way that from my Main Menu i click on (for example) “Servers” and after i click on “Servers” slider in Slider Gallery is automatically positioned(scrolling to) at “Servers” section?

    I was trying to solve this for days with common tricks but no go :(

    Of course if anyone other know how to do this please write it here(code please). Lars maybe?

  25. Ismail Mayat On 18th November 2009 at 10:11

    I am looking to implement this excellent plugin on a site, I have it working. My question what changes do I need to make so that I can get a span with image description to appear after the image?

    Regards

    Ismail

Comments are now closed.