jQuery - Creating a Slideshow

Skill

jQuery - Creating a Slideshow

Posted in:

Lately I have been doing a lot with jQuery and one item is a slideshow. Around the web you can find a variety of slideshows, all with slightly different implementations. Well today I am going to add to the already long list with a very simple solution. With the same code you can use this slideshow to display anything you can put into html.

You can check out an example of this below or over at HyperQuake's new site. The example just slides through a few images. I should mention that all of the contents of the slideshow is available at load, so the current implementation would probably not be the best for lots of large images. But for custom html pieces, as with the HyperQuake site, it is very nice because all the content is crawlable and therefore available to search engines for indexing.

To get things rolling we'll take a look at the html for the pretty example above. In the code below you will see a surrounding div (id slideshow-area) which holds our slideshow content scroll area and our next and previous buttons. Inside our scroll area we have a div to hold the content and finally the content itself. As far as html goes this is pretty simple stuff.

<div id="slideshow-area">
  <div id="slideshow-scroller">
    <div id="slideshow-holder">
      <div class="slideshow-content">
        <img src="eureka_small.jpg" />
      </div>
      <div class="slideshow-content">
        <img src="wallace_gromit_small.jpg" />
      </div>
      <div class="slideshow-content">
        <img src="dead_like_me_small.jpg" />
      </div>
    </div>
  </div>
  <div id="slideshow-previous"></div>
  <div id="slideshow-next"></div>
</div>

As I mentioned earlier you can replace the <img with any HTML content you want. That pretty much takes care of the html part.

CSS is up next, it is slightly more complicated than the html but nothing too crazy. The first piece to look at is the positioning and sizing of main slideshow area and scroller, which can have pretty much the same css. We do however add a border to our area to bring it out a little. The code below is fairly understandable, I make sure to set the position to relative so that I can easily position the next and previous buttons absolutely.

#slideshow-area, #slideshow-scroller {
  width: 500px;
  height: 500px;
  position: relative;
  overflow: hidden;
  margin: 0 auto;
}

#slideshow-area {
  border: 1px solid #000;
}

We are also going to set the height of the content holder to 500px, same as the area.

#slideshow-holder {
  height: 500px;
}

The next two items are the previous and next buttons. They take a little bit more work to make sure they are in the correct position. The buttons also have background images for pretty arrows (sorry IE6 users it may look bad since the arrows are png files). I also set the cursor to hand and pointer - for browser compatibility. And finally we also have classes to identify and float left each piece of content in the slideshow.

#slideshow-previous, #slideshow-next {
  width: 50px;
  height: 50px;
  position: absolute;
  background: transparent url("arrow_left.png") no-repeat 50% 50%;
  top: 225px;
  display: none;
  cursor: pointer;
  cursor: hand;
}

#slideshow-next {
  display: block;
  background: transparent url("arrow_right.png") no-repeat 50% 50%;
  top: 225px;
  right: 0;
}

.slideshow-content {
  float: left;
}

Well onto the real work, we now have to create the JavaScript to handle our functionality. jQuery makes this relatively simple though. First item is adding code to the document ready event.

var totalSlides = 0;
var currentSlide = 1;
var contentSlides = "";

$(document).ready(function(){
  $("#slideshow-previous").click(showPreviousSlide);
  $("#slideshow-next").click(showNextSlide);
 
  var totalWidth = 0;
  contentSlides = $(".slideshow-content");
  contentSlides.each(function(i){
    totalWidth += this.clientWidth;
    totalSlides++;
  });
  $("#slideshow-holder").width(totalWidth);
  $("#slideshow-scroller").attr({scrollLeft: 0});
  updateButtons();
});

The code starts out with a few variables that we will use. These hold the total number of slides, what slide we are currently on, and an array of content slides. Our document ready handler starts by adding click event handling to our previous and next buttons. We will define these functions shortly. Next, we figure out the total width of our content by using a simple selector on the slideshow-content class. We then run the results through jQuery's each function adding the widths as we loop through the items and also counting number of slides.

Next we need to create the two functions showPreviousSlide and showNextSlide. These two functions do mainly three things: change current slide number, update the buttons, and scroll the content. These functions along with support functions are below.

function showPreviousSlide()
{
  currentSlide--;
  updateContentHolder();
  updateButtons();
}

function showNextSlide()
{
  currentSlide++;
  updateContentHolder();
  updateButtons();
}

function updateContentHolder()
{
  var scrollAmount = 0;
  contentSlides.each(function(i){
    if(currentSlide - 1 > i) {
      scrollAmount += this.clientWidth;
    }
  });
  $("#slideshow-scroller").animate({scrollLeft: scrollAmount}, 1000);
}

function updateButtons()
{
  if(currentSlide < totalSlides) {
    $("#slideshow-next").show();
  } else {
    $("#slideshow-next").hide();
  }
  if(currentSlide > 1) {
    $("#slideshow-previous").show();
  } else {
    $("#slideshow-previous").hide();
  }
}

Starting with the last function, updateButtons, it handles showing and hiding the the appropriate buttons. It looks at what the current slide is and compares it to how many we have or if it is greater than one - pretty easy stuff. The next function is where all the work is done for scrolling our area. We first figure out where we need to scroll to. This is done by adding the width's of the previous slides together. Once the amount is calculated we just need to animate our scroller to the correct place using jQuery's animate function. We pass the attribute to change and how long it should take to do it. With these functions called by our previous and next button clicks we have our slideshow.

That wraps up this tutorial. I hope that at least one person finds something they need from this guy. As always if anyone has any questions feel free to drop us a comment or send us a question through our contact form. Until next time, keep killing time on the Internet.

Update 03/05/2009

I have updated the source code, there was a slight bug when refreshing the page or using the back buttons. This is fixed by resetting the scroll left on the scrolling div and calling an update on the buttons in our document ready function. The code above has been modified. Also here is the updated document ready function.

$(document).ready(function(){
  $("#slideshow-previous").click(showPreviousSlide);
  $("#slideshow-next").click(showNextSlide);
 
  var totalWidth = 0;
  contentSlides = $(".slideshow-content");
  contentSlides.each(function(i){
    totalWidth += this.clientWidth;
    totalSlides++;
  });
  $("#slideshow-holder").width(totalWidth);
  $("#slideshow-scroller").attr({scrollLeft: 0});
  updateButtons();
});

Chris
03/09/2009 - 04:49

This is a great Slideshow! I don't understand how you don't have any comments.

I want to use your slideshow in my project, but there are two features I would love to have.

You have any idea how to make it run by itself on a timer, so that if the user does not click on any of the buttons, it continues to the next picture after a set amount of time? If you can get that to work, do you have any idea how i can get it to pause when the user hovers over it?

Also, I would like to make the arrows show up only when the user hovers over each of them. Is that possible?

Again, great script! I hope you can help me out.

reply

Hans
04/02/2009 - 11:50

I agree. Nice script! I looked out for it to be posted a long time a go. Strange thing indeed that there are so little comments.

I also wanted to ask the same thing as Chris: a self sliding slideshow, that stops sliding when hovered on.

@Chris: you can make sure the buttons are only visible when hovered on by changing the background with CSS to something that's not visible (no image or a transparent gif) with CSS. You would need to add something like

#slideshow-next:hover {
background-image: "nonexisting.gif"'
}

Search for the CSS "pseudo classes" (like hover) on the internet. I'm sure you'll find some useful information.

reply

Mark
05/10/2009 - 00:26

I agree, Beautiful simple script!

reply

Richard
07/19/2009 - 05:59

That is absol. brilliant. Thank you ever so much. Works a gem :D

Does anyone know how to add a timer to it aswell. So the image will scroll after about 10 seconds?

reply

xaccrocheur
11/06/2009 - 05:19

... And to add easing, just replace the duration value with :

 
{
     duration: 'slow',
     easing: 'easeOutBounce'
    }

Look here for all easing methods
http://www.learningjquery.com/2009/02/quick-tip-add-easing-to-your-animations

I must say, this implementation is brilliant because it's the only one I know of that takes the scrolled items divs withs and ADD them up to automagically calculate the scroll amount : All the others require the TOTAL width to be hard coded, witch makes no sense in a programmatical environment : Loop and add one div and you're out of bounds. Not so here. Thank you very much, man.

reply

Anonymous
02/26/2010 - 02:42

HI All,

i copy all the code above.
it not working on my testing page.

It show the pic and the arrow but when i click the next pic arrow it do nothing.

Can anyone send me the source which working?
my email is calvinkwoo3000@gmail.com.
Thanks.

reply

Add Comment

Put code snippets inside language tags:
[language] [/language]

Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]

See here for supported languages.

Javascript must be enabled to submit anonymous comments - or you can login.

Sponsors