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 posts

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <title>Slider Gallery</title>
    <style type="text/css" media="screen">
    <!--
        body {
            padding: 0; 
            font: 1em "Trebuchet MS", verdana, arial, sans-serif; 
            font-size: 100%;
            background-color: #212121;
            margin: 0;
        }

        h1 { 
            margin-bottom: 2px; 
        }

        #container {
            background-color: #fff;
            width: 580px;
            margin: 15px auto;
            padding: 50px;
        }
        
        /* slider specific CSS */
        .sliderGallery {
            background: url(http://static.jqueryfordesigners.com/demo/images/productbrowser_background_20070622.jpg) no-repeat;
            overflow: hidden;
            position: relative;
            padding: 10px;
            height: 160px;
            width: 560px;
        }
        
        .sliderGallery UL {
            position: absolute;
            list-style: none;
            overflow: none;
            white-space: nowrap;
            padding: 0;
            margin: 0;
        }
        
        .sliderGallery UL LI {
            display: inline;
        }
        
        .slider {
            width: 542px;
            height: 17px;
            margin-top: 140px;
            margin-left: 5px;
            padding: 1px;
            position: relative;
            background: url(http://static.jqueryfordesigners.com/demo/images/productbrowser_scrollbar_20070622.png) no-repeat;
        }
        
        .handle {
            position: absolute;
            cursor: move;
            height: 17px;
            width: 181px;
            top: 0;
            background: url(http://static.jqueryfordesigners.com/demo/images/productbrowser_scroller_20080115.png) no-repeat;
            z-index: 100;
        }
        
        .slider span {
            color: #bbb;
            font-size: 80%;
            cursor: pointer;
            position: absolute;
            z-index: 110;
            top: 3px;
        }
        
        .slider .slider-lbl1 {
            left: 50px;
        }
        
        .slider .slider-lbl2 {
            left: 107px;
        }
        
        .slider .slider-lbl3 {
            left: 156px;
        }

        .slider .slider-lbl4 {
            left: 280px;
        }

        .slider .slider-lbl5 {
            left: 455px;
        }
    -->
    </style>

    <!-- updated to jQ 1.2.6 and UI 1.5.2 2008-11-28 -->
    <script src="jquery-1.2.6.js" type="text/javascript" charset="utf-8"></script>
    <script src="jquery-ui-full-1.5.2.min.js" type="text/javascript" charset="utf-8"></script>
    
    <script type="text/javascript" charset="utf-8">
        window.onload = function () {
            var container = $('div.sliderGallery');
            var ul = $('ul', container);
            
            var itemsWidth = ul.innerWidth() - container.outerWidth();
            
            $('.slider', container).slider({
                min: 0,
                max: itemsWidth,
                handle: '.handle',
                stop: function (event, ui) {
                    ul.animate({'left' : ui.value * -1}, 500);
                },
                slide: function (event, ui) {
                    ul.css('left', ui.value * -1);
                }
            });
        };
    </script>
</head>
<body>
    <div id="container">
        <h1>Slider Gallery</h1>
        <p>This shows a demonstration of a slider widget from the jQuery UI library used to create the same effect used on <a href="http://www.apple.com/mac/">Apple's web site</a>.</p>
        <p><a href="/slider-gallery">Read the article, and see the screencast this demonstration relates to</a></p>

        <div class="sliderGallery">
            <ul>
                <li><img class="pb-airportexpress" src="http://static.jqueryfordesigners.com/demo/images/pb_airport_express.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_airport_extreme.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_timecapsule_20080115.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_keyboards20070807.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_mighty_mouse.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_cinema_display20071026.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_mac_pro_20070622.jpg" /></li>

                <li><img class="pb-macmini" src="http://static.jqueryfordesigners.com/demo/images/pb_mac_mini.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_macbook20071026.jpg" /></li>
                <li><img class="pb-macbookair" src="http://static.jqueryfordesigners.com/demo/images/pb_macbookair_20080115.jpg" /></li>
                <li><img class="pb-macbookpro" src="http://static.jqueryfordesigners.com/demo/images/pb_macbook_pro20071026.jpg" /></li>
                <li><img class="pb-imac" src="http://static.jqueryfordesigners.com/demo/images/pb_imac20071026.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_macosx_20080115.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_ilife_20080115.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_dot_mac_20080115.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_iwork_20080115.jpg" /></li>

                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_quicktime.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_aperture20080212.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_final_cut_studio2_20080115.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_final_cut_express_20080115.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_logic_studio_20080115.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_logic_express_20080115.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_shake_20080115.jpg" /></li>                    
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_apple_remote_desktop_20080115.jpg" /></li>
                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_xserve.jpg" /></li>

                <li><img src="http://static.jqueryfordesigners.com/demo/images/pb_xserve_raid.jpg" /></li>
                <li><img class="pb-xsan" src="http://static.jqueryfordesigners.com/demo/images/pb_xsan_20080115.jpg" /></li>
                <li><img class="pb-macosxserver" src="http://static.jqueryfordesigners.com/demo/images/pb_macosx_server20071016.jpg" /></li>                    
            </ul>
            <div class="slider">
                <div class="handle"></div>
                <span class="slider-lbl1">Wi-Fi</span>
                <span class="slider-lbl3">Macs</span>
                <span class="slider-lbl4">Applications</span>
                <span class="slider-lbl5">Servers</span>
            </div>
        </div>
    </div>
</body>
</html>

Comments

  1. juk On 3rd April 2009 at 09:04

    hi, This is very nice tutorial. It is working fine in ie and firefox but not working in google chrome can anyone help me in this issue i am struggling for past one week…………

  2. Nathan On 7th April 2009 at 04:04

    Hi everyone,

    Great tutorial! Just not sure how to get the text links to jump to the start of the list item? (example: ‘Macs’ goes straight to the beginning of the mac items.) I’ve edited my version and it moves okay, but not to the start of where it needs to, does this make sense?

    Thanks, any help is much appreciated :)

    N

  3. Mauro On 7th April 2009 at 19:04

    Please can you fix with jquery-1.3.2.min.js and jquery-ui-1.7.1.custom.min.js ? work only with previous version. thanks

  4. Craig On 9th April 2009 at 19:04

    I have implemented the jQuery slider on my site (http://www.italiantiecompany.com/ties.html) to display a list of products. It works flawlessly in FF, chrome and Safari, and somewhat well in IE 7 (no surprise here).

    Is there a way to code the slider to move more smoothly when the left and right arrows are clicked. The way it is implemented here causes the slider to jump to either end of the list while skipping everything in between. Any suggestions?

  5. cbass On 9th April 2009 at 23:04

    hi, quick question on the slider itself … is there any way to make the handle move more slowly when the left and right arrows are clicked, so that it doesn’t just skip over everything and run to the beginning or end of the list in one sweeping motion?

  6. Florence On 11th April 2009 at 19:04

    I am able to get this to work fairly well. However, I would like to be able to have text or comments move from the slider images to the viewing frame. I would like to add “comments” next to the image and I would like to then have the enlarged viewed image have a new link generated to open it a new browser window.

    I could put the content information in the “title” but how do I get it to moved to the new assigned spot.

    How do I add to the the jquery info that works onclick.

    function movepic(imgname,imgsrc) { document[imgname].src=imgsrc;

  7. Eyveneena On 12th April 2009 at 05:04

    Hi Remy,

    Thank You
    
  8. Alex On 21st April 2009 at 14:04

    overflow:auto; with javascript off give the solution for a sweet browser degrade

  9. Alex On 21st April 2009 at 19:04

    does anybody found a solution for the latest jquery release?

  10. Lamba On 23rd April 2009 at 23:04

    Hallo, first time, thank you for the fantastic tutorial! but i have a problem… my slider will be append to the content, the JS-Script also cant load if window is ready… how can i fix this. i would load the script after append the slider to content…

    (sorry 4 my bad english!)

    marco

  11. Yoosuf On 28th April 2009 at 02:04

    its nice and also the new design is really cool man, keep it up

  12. Rafael On 6th May 2009 at 20:05

    Hi,

    first of all, I find this slider great. And I would like to implement it into my website, which is a shopping cart (but still in tests). But when i was trying to put it, I’ve received an error message.

    If you check the main domain “www.bereco.lu”, you’ll see a banner on the top, and right there is where I want to replace this banner for the slider gallery instead. I’m sure you can make it, or at least, tell me how to do it (but step by step) ;-) I cannot because I have no idea about css, jquery, javascript, html, php, etc., I’m completely null!! ;-)

    This is the link to the Prestashop script: http://www.prestashop.com/en/downloads/

    And here I added a post to the forum: http://www.prestashop.com/forums/viewthread/18462/modules/applesslidegallery

    Last, just wanted to say a little difference between Apple’s slide and yours: the name of the products under the images, which I’ll need for my website.

    Thanks in advance and congratulations for your great job. Rafael.

  13. Gustavo On 10th May 2009 at 13:05

    Very cool, but brokes in i.E. 6.0 i didn“t tried in i.e. 7.0. congratulations for the site. Thanks. :)

  14. brian yang On 14th May 2009 at 16:05

    great tutorial! works in IE6 if we change the ‘margin-top’ declaration to ‘top’..

  15. Jaya On 14th May 2009 at 17:05

    Hey - This was a great tutorial ! But as I’m new to jquery I don’t really understand where exactly I can make modifications. If I need to move the slider by a certain amount each time we click on the left and right arrows instead of just to the extreme left and right - what do i do? $(”.control.prev”).click(function(){ $(’.slider’, container).slider(”moveTo”,”-=250px”); }); This was some code I saw in an earlier comment - please let me know where this change is to be incorporated.

    Thanks a ton, Jaya

  16. Mark On 15th May 2009 at 20:05

    Nice but not working in FF 3.0.10 :-(

  17. mark On 16th May 2009 at 08:05

    thanks for the tutorial..but where to download this file jquery-ui-full-1.5.2.min.js

  18. chad On 19th May 2009 at 00:05

    in your ‘Slider Code’ example above the minValue and maxValue should be min and max. i spent a good hour trying to figure out why it kept stopping at 100px. but hey, thanks for the easy script.

  19. Cristian Tudose On 19th May 2009 at 06:05

    Have you try to see this demo in IE6 ? And also your web page don’t look very well in IE6. No transparency for png … :) But the tutorials are great!

  20. Cristian Tudose On 19th May 2009 at 06:05

    Hi. There is the css for IE6. You may need to adjust some values like margin-top or width.

    .slider { width: 542px; height: 17px; top: 120px; margin-top: 120px; margin-left: 40px; padding: 1px; position: relative; background: none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, src=’/pathto/productbrowserscrollbar20070622.png’); }

    .handle { position: absolute; cursor: move; height: 19px; width: 181px; top: 0px; background: none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, src=’/pathto/productbrowserscroller20080115.png’); z-index: 100; }

  21. ycc On 20th May 2009 at 02:05

    It doesnot work in Firefox 3.0.10. When I drag the scroll bar, contents donot slide.

  22. Sean On 20th May 2009 at 02:05

    Doesn’t seem to work in Firefox 3.0.10

  23. Mark On 20th May 2009 at 13:05

    Really having problems with this can’t seem to get the ul to move, there is a problem with the left value. http://roondogid.co.uk/test/alex

  24. Gav On 24th May 2009 at 16:05

    Aweswome bit of jQuery!! Looks practically identical to the Apple effect!

    How could this be extended to have an link on each of the images when clicked? Any ideas on how this could be done - will have a crack at it myself and come back with my findings!

    Cheers, Gav

  25. PHP Hosting On 29th May 2009 at 03:05

    Cool example it looked fairly regular until I noticed the labels under and near the scrollbar. I love that you did this with javascript rather than flash.

Leave your own comment
  • http://