The slider that Steam uses for their sales is pretty cool. It features your typical product slider in the center of the page, but also has a smaller slider behind it that creates a really neat visual effect.

Here's what I'm talking about if you haven't seen it:

Steam Holiday Sale 2012 Slider
Steam Holiday Sale 2012 Slider

As you move between slides the background images also slide along to the correct position.

It's really just three separate sliders on the page, each reacting to your input in pretty much the same way. I decided to recreate it using jQuery (Steam uses pure, unadulterated man-sized Javascript to do it) and I decided to share my results with you. Because I love you.

Here's my final result in screenshot format:


Steam Slider
Steam Slider

All images were stolen without remorse from Steam. If Steam or Valve would like me to remove these images I will happily replace any or all of them with images of unicorns :)

Getting Started

For this tutorial you will probably need some images. The slider uses three types of images, a "capsule" image for the little thumbnail things, a "dark" banner behind the main slider and of course the main "banner" image. If you don't have some images, some images will be appointed for you. Right hyah!

Here is my file structure for this little project:

  • banner
    • 01.jpg
    • ...
    • 12.jpg
  • banner_dark
    • 01.jpg
    • ...
    • 12.jpg
  • capsules
    • capsule_01.jpg
    • ...
    • capsule_12.jpg
  • images
    • arrow_left.png
    • arrow_right.png
  • js
    • jquery.js
    • jquery.hoverIntent.min.js
    • slider.js
  • json
    • slider_settings.json
  • index.html
  • style.css
  • style.scss


I've kept a whole bunch of stuff inside a JSON file because JSON is awesome and if I ever used this in an actual project, I'd want the images and settings to be easy to update. By keeping it all in a JSON file it is super easy to update.

Let's take a look at the JSON file first:

It's a pretty standard JSON file, we have some settings at the top to specify slide width and the dark slide widths, then following on from that are two arrays. The first array are for today's deals (the thumbnails across the top) and the second array is for yesterday's deals (the thumbnails across the bottom.)

Inside each item is a name, link, capsule, banner and banner_dark. Capsule, banner and banner_dark are image locations for the thumbnail, large banner and darker, smaller banner in the background, respectively.


Here's some sassy CSS that will make everything look pretty. The core of this experiment is javascript, so I won't go in to the CSS, it's pretty standard stuff:

If SASS isn't your thing, that's cool, I've included non-minified CSS in the download.

Our HTML Markup

Let's take a look at our HTML markup for our slider. Steam uses some sort of CMS I would image so a lot of their mark up would be generated by the CMS itself. Instead, for this tutorial I'm going to build our slider from the JSON file, so all we need are some empty elements to chuck our images in to.

At the bottom there I've also included jQuery (latest) and hoverIntent. As the thumbnails are being created by javascript, we need a special modified version of hoverIntent by Hernan. Feel free to grab either the minified or non-minified versions. Whatever floats your goat.

Alrighty, so we have our images, our json, the CSS and now our HTML markup, what's left? Oh right, the...


Create your slider.js file and start off with the good old document.ready() shorthand:



Make sure everything we add is inside that function.

Start off our code with the following:

Here we have  a bunch of variables that cache some selectors for us. These are all the elements on our HTML page that we're going to be manipulating with Javascript.

Underneath the settings we have some code that will load the JSON file via the jQuery $.getJSON function. Once we've gotten our JSON, we assign our JSON data to some variables so we can actually do stuff with the information later.

Once we've assigned all our variables, I've told it to run three functions: populateToday(), populateYesterday() and populateSlide(). I'll discuss these functions a little later.

Finally, at the bottom there we have a handy dandy function I unceremoniously stole from StackOverflow for randomising an array. This will randomise both the deals_today and deals_yesterday arrays.

Heeeeere's populateToday() and populateYesterday()!

Both of these functions iterate through the two arrays from the JSON file and them takes that information from those arrays and then runs that information through the renderCapsule function. The render capsule function creates a div with the image inside it and then appends the div to the either todayDeals or yesterdayDeals. Smashing!

While it does that, it's also adding each of these "deals" to an allDeals array. This is because we need an array that combines both todays and yesterdays deals for the main slider feature, while keeping the thumbnails separated in to Today and Yesterday.

Next up we have our populateSlides() function which will iterate through each of the allDeals array. This adds the big colourful image to the main slider and a dark and moody image to the left and right sliders. Just like the populateToday() and populateYesterday() functions, it iterates through each of them and handballs them off to either renderSliderItem() which will put together a slide for the main slider or to renderDarkSliderItem() which will create one for the left and right sliders.

There's some real funkiness going on at the end of populateSlides() there, what's that all about? This ugly bit of code will add an additional slide to every slider. The left and main sliders will get an extra of slide 12 and the beginning and the right slider will get an extra of slide 1 right at the end. This is so we can smoothly transition from the end back to the beginning and vice-versa.

And now we have our slide control functions. These are functions that will let us navigate this crazy beast.

First up we have a hoverIntent being called on $(".deal_nav .item). When you hover over it, and wait the mandatory 400 milliseconds, it will get the data-num attribute and call setActiveThumbnail (which will, uh, set the active thumbnail) and then slideTo() that number.

Steam appear to use a 500 millisecond delay on their hovers before something happens, but I'm impatient, so I opted for 400 milliseconds. If you're a delay nazi feel free to take that delay all the way down to zero for some insta-switching action.

Following on from the hoverIntent bidniz, we have some click functions for the previous and next buttons. Not only can you click the arrows but you can also click on the darker sliders themselves to navigate left or right.

setActiveThumbnail() will take a number, any number and make the thumbnail that correlates to that very number the active one.

slideLeft() and slideRight() will do absolutely nothing if the sliderContainer is animating. This prevents people from breaking your slider when going from slide 1 to slide 12 in reverse. These functions call slideTo() based on whatever the active slide is at the moment. If you're on slide 1 and call slideLeft(), instead of going to a non-existent slide 0, it goes off and calls slideOffsetLeft(), which is some pure lunacy I'll discuss in a minute. slideRight() does the same thing and calls slideOffsetRight() if going from 12 to 1.

getActiveSlide() will investigate the page and find which of the thumbnails have the "active" class.

slideTo() is where the magic happens. Here we move the main slider as well as both of the smaller sliders at the same time using some math. Hopefully the math is fairly easy to understand. I think it a case of trial and error to see what happened.

slideOffsetLeft() and slideOffsetRight() are functions that are called when going from slide 1 to slide 12 (in reverse) and from slide 12 to slide 1 (forwards.) The gist of it is this: When you're on slide 1, slide to slide 0 (which if you remember from earlier, is a duplicate of slide 12), once complete, set the CSS of the slider (instead of an animate) to the last slide. This will seamlessly transition to slide 0, then to slide 12. So if the user keeps pressing back, it will look like the slider is just continuing backwards. We are then duplicating that logic over to the left and right sliders.

So that's all of the javascript!

Here's what the final javascript file looks like:

Phew. Let's see what that looks like. Oh yeah, lookin' good.

Fun with 3D

The left and right sliders are their own separate elements which means we can play around with their styles without affecting the other sliders. Which means we can do things like... this:

3D Steam Slider
3D Steam Slider

Woah. We can do that by adding the following CSS3, obviously it will only work in CSS3-capable browsers:

I've added a button to the bottom of the demo page with that toggles the 3D effect. The source files also include the 3d toggle.

Download Source Files