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:
- Markup that allows us to place several items within a list, and that overflows out of sight.
- A slider widget to control what subsection of products we can see.
- 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:
- Better scrolling effect, in particular, fast scroll for the bulk of the animation, and slows down when it’s settling on the final item.
- Turn it in to a plugin.
- The arrow can be turned in to handlers to slide the handle only part of the distance, rather than all.
- 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.
- Anything else you can think of!
You should follow me on Twitter here I tweet about jQuery amongst the usual tweet-splurges!
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
<!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>

Play QuickTime version
Play Flash version

Martin On 5th February 2009 at 10:02
hi
anyone knows how to make it auto advance to the next picture or label every let’s say 5 seconds?? sorry for being total newb in jq
Cole On 5th February 2009 at 23:02
I am adding in with Tom. I too have been struggling with getting the text to format underneath the image. Any thoughts what needs to be done to get the text to go underneath the images instead of to the left of it??? Line breaks break the formatting……so that won’t work.
Tom On 6th February 2009 at 12:02
Yes its a bit of fiddle Cole… Im playing with the CSS so I will let you know if I have any joy!
Tom On 6th February 2009 at 14:02
Cracked it! http://silverworkshosting.co.uk/360motion/index.php
Mohsin Sheraz On 12th February 2009 at 12:02
Hi all!
I need some help her, new to Jquery …. I got it all to work with jquery-1.2.6.js ….. but when I try to get it working with the current UI core and Widget slider in Stable mode (downlaoding jquery-ui-personalized-1.5.3.min.js) it doens’t seem to work …
So maybe someone could give a quick overview of the current teps to get this great effort working!
Tnx
Adrian Friend On 15th February 2009 at 10:02
Don’t know whether this will help anyone but I was getting frustrated with having to set a width on the UL to get it to work in IE.
var productWidth;
if (jQuery.browser.msie) { //calculate the outer width of the LI (with padding and border) //and multiply by the number of LIs in the UL (using the .size() method) !add 2 for the offset (is this right?) var liTotal = ($(’UL LI’, this).outerWidth() * $(’UL LI’, this).size()) + 2; //add the left & right margin together var liMargin = parseInt($(’UL LI’, this).css(’margin-left’), 10) + parseInt($(’UL LI’, this).css(’margin-right’), 10); //multiply the margins by the total number of LIs var allMargins = liMargin * $(’UL LI’, this).size(); //add the total size of LIs (pixels) and total of the margins (in pixels) var ulWidth = liTotal + allMargins; //calculate if there is an LI at the end thats only partially shown as a % var shownLIs = (1 - parseFloat($(this).width() / ulWidth).toFixed(2)) * 100; //then calculate the width thats shown in actual pixels. We have to add this to the productWidth (it will cause an error otherwise) var leftLIs = (($(’UL LI’, this).outerWidth() + liMargin) * shownLIs) / 100; //set the ulWidth as a string appended ‘px’ to the end so we can use in setting the width var ulWidthPx = ulWidth + ‘px’;
//set the width of the UL $(’UL’, this).css(’width’,ulWidthPx); //now we can get the correct productWidth for the slider productWidth = parseInt(($(’UL’, this).innerWidth() - $(this).outerWidth()), 10) + parseInt(leftLIs.toFixed(0), 10); } else { productWidth = ul.innerWidth() - $(this).outerWidth(); }
Hope that all makes sense. It probably could do with tidying up and refactoring a bit but it seems to work well.
John Keese On 18th February 2009 at 16:02
@Mohsin - I’m right there with you. This works with jquery 1.2.6 and the ui-core from the demo — but will NOT work with jquery 1.3.1 and ui-core 1.5.3
Anyone else having the same problem?
Remy On 18th February 2009 at 16:02
Just catching up on this thread about jQuery + UI. Currently 1.3.1 doesn’t work with 1.5.3 UI.
This blog post explains the compatibility issues, and which versions work: http://blog.jquery.com/2009/02/12/jquery-ui-17-is-the-new-16/
Johnathen On 20th February 2009 at 03:02
anyone able to get this working with text? i have tried and tried but everything just throws a hissy fit once the element is set to display: block rather then inline;
thanks
Johnathen On 20th February 2009 at 03:02
oh an just wanted to say a fix to get it working with current jquery, try this:
then change every $ to $j that this script has :) should work
Ravi On 23rd February 2009 at 20:02
Hey , Great tutorial, However I am having the following issue when I have multiple slider galleries. The problem I run into is when I use the slider on gallery one, it effects both gallery one and gallery two. It appears like the slider is getting wired to all the galleries - can you help me in fixing this?
Here is the code I have:
/* Slider specific customizations */ var container = $(’div.sliderGallery’); var ul = $(’ul’, container);
Cole On 23rd February 2009 at 23:02
Ok so I found a solution to using text within this code. I’m not satisfied with it and it can prove to be a pain in the ass but I need text on my slider and no one has shown me anything else. Just create a section un-ordered list below the images. Give an Id tag to your images and in the CSS change the ul tag to your id name. Next do the same thing and place your text here. Give it a position of absolute and use margins to push it down to the bottom (or wherever you are looking to go….I’ll supply a link to my example page when I get home from work. Like I said, a not so great way but it works. Please if anyone that knows this jQuery stuff please fill some of us in on how we can do this!
Mike On 25th February 2009 at 01:02
John, having the same issues with 1.3.1 as you.
Daniel On 25th February 2009 at 02:02
Hello,
thanks to everyone. i try to implement the slider gallery in an wordpress 2.7 article the following way:
<!--more-->
but have no luck. The Gallery appears visually perfect, both in ie7 + firefox but i can“t move the slider nor click on the slider background. Mouse-Over: Cursor changes to cross-symbol Mouse-Click: Cursor flickering with Button-Hand-Symbol
Does anyone know, whats going wrong?
Abdel On 27th February 2009 at 22:02
thanks a lot for this tutorial. It will sure help me set up my portfolio the way I imagined it.
Johnathen On 1st March 2009 at 14:03
@Mike: did you do what i said to do to get it working with jquery 1.3.1?
i have just managed to get it working with text with still leaving the display as inline. will post back the solution once it’s finalised and an example of where it is running.
only other problem i have noticed is when you click the links, ie applications/server etc, that the slider doesn’t jump to them but instead the position you click on the bar, so if i click applications on the very right it should have applications in the middle of my screen but instead it’s far to the right showing the end selection of applications and the next category, not very good as customers will miss the products.
Richard On 9th March 2009 at 15:03
Hi,
I noticed that there have been a number of requests for getting this scroller to autoscroll initially which have not be answered. I also need to be able to get the scroller to autoscroll. On this web page where I am using the scroller I would like to have it initially scroll slowly through all 25 images and then stop. If it could then scroll back to the beginning would be great but I would be happy with just the initial scroll.
Cheers, Richard
brian On 9th March 2009 at 22:03
@remy: maybe you should put that it doesn’t work with the current version of jQuery in the post; not in the messages, as people could be having problems.
i’m a fan of all your tutorials, thanks bro!
Web Design On 11th March 2009 at 08:03
Excellent tutorial thanks for sharing, bookmarked this for later use as i plan to use it on a few sites.
chilli On 11th March 2009 at 11:03
Is it possible to AutoAnimate this slider so that it woul loop and change content let’s say every 3 second?
increase page rank On 19th March 2009 at 13:03
is there other example? i need the one like moving box
Darren On 20th March 2009 at 20:03
Is there any way of running multiple gallerys on one html document. I have a problem where the slider button slides all the galleries. Can anybody help?
Jim On 30th March 2009 at 07:03
Hi, I can get it to work with your version of JQuery (1.2.6) but can’t get it to work with the new version of JQuery (1.3.2) even though I tried Johnathen’s method. Any tips?
bryan On 30th March 2009 at 20:03
Yeah i love this script, but i am having one hell of a time getting text odisplay underneath. It would be nice if we it wasnt an inline element so we could set a width to the “li”…
Sean On 31st March 2009 at 12:03
I cant get this to work at all. I have tried every combination from the video tutorial and the source code of the page. Nothing seems to work for me!!!
The slider was sliding but the content wasn’t moving.