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 usual the tweet-splurges!
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>
New
Play QuickTime version
Play Flash version
Basti On 20th November 2009 at 10:11
Hey, I tried to run the gallery local, but it doesn’t work. Could it be that the gallery does not support jquery 1.3.2 and UI 1.7.2?
Would be thankful for help.
Thank you!
Alex Mortensen On 20th November 2009 at 18:11
FYI I’ve figured it out. So if anyone is interested or have problem like me here is your solution.
I just added hollowing code to Javascript:
$(”.point-servers”).click(function(){ $(’.slider’, container).slider(”moveTo”,”1200px”); });
So in the end it is looking like this:
An i am calling slider to move from a link like this:
codehere:
But now i am stuck in another problem. How to call slider to move from link from another page..Everything mentioned in this tutorial and my addon will work only for that site with SliderGallery.
Fabio P On 8th December 2009 at 12:12
Hi, I’ve a problem with scrolling in a modified version of the slide: http://www.fabiodesign.com/gallery2.html The slideGallery has the same width of the window and it works perfectly. The problem is that if I want to resize the window, the slide will not scale proportionately. I try to refresh the slide copying the same js of window.load and pasting it under window.onresize event. It refresh the proportion of the slide, but then appears a overlap effect. Who can help me? Thanks
Fabio
Eric Dubois On 10th December 2009 at 18:12
I have nearly completed a conversion of slider-gallery to work with the latest version of Jquery and UI.
- I added a sliderContainer around the slider, which contains the full scrollbar background.
- I reduced the width of the slider to the length the scroller can travel.
- I added auto margins to the slider container to center it.
- I added negative margin to the scroller (half the width of the scroller) so the scroller is centered on the click position.
- I added incremental buttons to the right and left arrows.
- I added clickable areas to the dead areas between the slider and sliderContainer to go straight to the beginning or end.
http://www.ericdubois.com/jquerytests/slidergallery.phpMost of my testing has been on Mac. It works perfectly in Safari, Firefox, Opera, iCab, Camino, and Chrome. It does not work at all in Netscape.
In Windows, it works well in IE8, but the scroller and test are approx 20px too low in IE6 and IE7. It looks like they don’t like the scroller’s negative margin. I would appreciate your assistance in troubleshooting that part.
This version has some elements colorized to help troubleshoot: http://www.ericdubois.com/jquery_tests/slider_gallery3.php
Eric Dubois On 10th December 2009 at 18:12
Note: The underscores somehow got converted to em tags. The correct link is: http://www.ericdubois.com/jquerytests/slidergallery.php
Eric Dubois On 10th December 2009 at 21:12
Update: I added noscript style definitions to turn sliderGallery overflow to auto and sliderContainer display to none. This improves degradation when Javascript is disabled. http://www.ericdubois.com/jquerytests/slidergallery.php
Jose Lobato On 28th December 2009 at 19:12
Has anyone try to make work in a wordpress site? I have a problem.
The images does not load they just show an “?” icon. When I click on other thing they appear, but of course it is too late as long as the size has been already calculated. Does anyone know why is this happening?
Thanks guys.
Tom On 3rd January 2010 at 20:01
Is there any way of making this scroll vertically? Cheers.
thamizh On 6th January 2010 at 08:01
I tried to run the gallery local, but it doesn’t work. the navigation links are not working properly help me !
Fabrizio On 12th January 2010 at 12:01
Has anyone implemented autoscroll?
Gav On 16th January 2010 at 17:01
Awesome tutorial Remy - I’ve deployed this on one site and the boss was visually impressed at what jQuery could do! I only hope to learn half of what you know on jQuery and i’d be happy! :-)
Thanks again, your hard work is much appreciated! Gav
Gav On 17th January 2010 at 23:01
Got this working pretty well on this site - http://www.kymco.co.uk
However I have a small issue with the slider, when I click on the slider you will notice the left hand side of the slider image moves across slightly and doesn’t line up correctly with the image anymore.
Anyone have any ideas why it is doing this?
Cheers
Gav On 18th January 2010 at 00:01
Bit busy tonight!! (Sorry my last message I promise!)
Found an example from one of the comments on this article (see link below) - Wonderful and works really well, I just wondered if the javascript code could be modified to be placed within an document.ready() rather than using the older window.onload function? I only ask as I tried to implement some other minor jQuery effects that require the document.ready() furthermore as far as I know document.ready is the better alternative - can anyone help me out - thanks.
http://www.ericdubois.com/jquerytests/slidergallery4.php
Adrian On 18th January 2010 at 10:01
Hi. This Tutorial ist really great! But i need a function that remember the position where ive been.
Example: I click on Applications und Press F5 for refresh. Then the active position should be Applications again. Like on apple.com
Micah On 20th January 2010 at 00:01
Hey Remy, I love this little slider. It’s almost perfect for what I need.
As I’m sure you’ve heard over and over, I’m using Wordpress and was wondering how I could turn this slider into something more dynamic. It seems the basic implementation you presented gives a static version, but I think incorporating this with something like thickbox, using thumbnails and original sized photos would extend the functionality! It’d be a great slider to tie in with something like NextGEN as well. :o)
Thanks for your hard work!
Matt Watts On 26th February 2010 at 01:02
Remy,
Just wondering if your patch for UI 1.7.2 was available yet? a large amount of our other functionality hinges on 1.7.2 and Core 1.4.2 and it would be good to have a fix if possible.