Create a Slick and Accessible Slideshow Using jQuery

Accessible Slideshow.

In this in-depth web development tutorial, you’ll learn how to create a usable and web accessible slideshow widget for your site using HTML, CSS, and JavaScript (jQuery). In the process, you’ll see the concept of Progressive Enhancement in action.

Final Result

Clicking on the image below will take out to a live demonstration of the slideshow widget in action.

Final Result.

Download source files

You can download the source files for this tutorial to study. Along with the entire jQuery script used in this tutorial, the source file package also contains a PSD file named mockup-slideshow.psd for the web layout of the demonstration page, as well as the CSS background images and additional auxiliary files used to create the slideshow.

Setting the foundations

The most important part of any good web component is a solid HTML structure.  A semantic foundation means that your content will be web accessible in virtually all browser clients.

Our content’s structure involves a div called #slideshow that serves as the container for our slideshow. Nested inside it is another div called #slideContainer that holds the slides, which are divs with a class set to .slide.

Block 1: HTML markup

<!-- Slideshow HTML -->
<div id="slideshow">
  <div id="slidesContainer">
    <div class="slide">
      <!-- Content for slide 1 goes here -->
    </div>
    <div class="slide">
      <!-- Content for slide 2 goes here. -->
    </div>
    <div class="slide">
      <!-- Content for slide 3 goes here. -->
    </div>
    <div class="slide">
      <!-- Content for slide 4 goes here. -->
    </div>
  </div>
</div>
<!-- Slideshow HTML -->

In example 1 below, you’ll see how text-based browsers, and browsers incapable of rendering CSS and JavaScript, will see our slideshow. It’s important to note that all of our content is easily accessible; we’ve hidden nothing from the user – ensuring that everyone will have the ability to view our content.

There is also no markup for the left and right arrow controls, which we will insert into the DOM later on using JavaScript. Having them in the content structure level would be confusing to individuals without CSS or JavaScript capabilities.

Example 1: HTML content structure of the slideshow

Tip: Test web accessibility first, and often. When working on anything new, you should always test your HTML structure for accessibility. You can use a free web application called WebAnywhere for screen reader web accessibility tests to simulate how a person using a screen reader will interact with your content.

Styling the slideshow

The next step to a strong design is having a good set of styles that consider the possibility that the user has JavaScript disabled.

For #slidesContainer, we set the overflow property to auto so that scroll bars appear when our content overflows over the set height of 263px (the height of our slides).

Block 2: #slidesContainer CSS

#slideshow #slidesContainer {
  margin:0 auto;
  width:560px;
  height:263px;
  overflow:auto; /* allow scrollbar */
  position:relative;
}

We have to reduce the width of the .slide div class by 20px to accommodate the right hand scroll bar that will appear when JavaScript is turned off.

Block 3: .slide class CSS

#slideshow #slidesContainer .slide {
  margin:0 auto;
  width:540px; /* reduce by 20 pixels to avoid horizontal scroll */
  height:263px;
}

Without JavaScript, our content is still accessible; users can scroll up and down using to view our slides. Just like making a website mobile-friendly, we want our content to be as convenient to use as possible.

Example 2: Slideshow without JavaScript

Alternatively, you can give the .slide style rule a float:left; property so that instead of scrolling vertically, users can scroll horizontally.

Left and right arrow CSS

To save some JavaScript rendering resources, we’ll declare style rules for the left and arrow controls that we will insert in the DOM via jQuery.

The elements will be <span> elements, so we declare a cursor property and assign it the value of pointer to change the mouse pointer when the user hovers over the controls. We use the text-indent property to hide the text out of sight, a CSS background image replacement method.

Block 4: Controls

/** 
 * Slideshow controls style rules.
 */
.control {
  display:block;
  width:39px;
  height:263px;
  text-indent:-10000px;
  position:absolute;
  cursor: pointer;
}
#leftControl {
  top:0;
  left:0;
  background:transparent url(img/control_left.jpg) no-repeat 0 0;
}
#rightControl {
  top:0;
  right:0;
  background:transparent url(img/control_right.jpg) no-repeat 0 0;
}

The best part… JavaScript

With our HTML and CSS in place, it’s time for the fun stuff. We’ll use the jQuery library to make our slideshow more interactive and animated.

The theory

The first thing we want to do is ‘undo’ the styles that we declared in CSS that deals with the JavaScript off scenario. This involves declaring CSS styles in JavaScript for #slidesContainer to remove its scroll bar. Additionally, we have to resize our .slide divs to 560px, which we reduced by 20px in to accommodate the scroll bar. We also want to float the divs to the left so that they are displayed side by side horizontally instead of stacked on top of each other vertically.

Then, by DOM manipulation, we insert a div called #slideInner that wraps around all of our slides that has a width equal to the total width of all the .slide div.

Finally, we insert left and right controls (with class names of .control) for user navigation; we do this in JavaScript so that browser clients that don’t have JavaScript enabled won’t see the controls.

Here’s the JavaScript code in its entirety for you to study, but we’ll go through it in detail afterwards.

Block 5: The entire jQuery script

$(document).ready(function(){
  var currentPosition = 0;
  var slideWidth = 560;
  var slides = $('.slide');
  var numberOfSlides = slides.length;
  
  // Remove scrollbar in JS
  $('#slidesContainer').css('overflow', 'hidden');
  
  // Wrap all .slides with #slideInner div
  slides
  .wrapAll('<div id="slideInner"></div>')
  // Float left to display horizontally, readjust .slides width
  .css({
    'float' : 'left',
    'width' : slideWidth
  });
  
  // Set #slideInner width equal to total width of all slides
  $('#slideInner').css('width', slideWidth * numberOfSlides);
  
  // Insert left and right arrow controls in the DOM
  $('#slideshow')
    .prepend('<span class="control" id="leftControl">Move left</span>')
    .append('<span class="control" id="rightControl">Move right</span>');

  // Hide left arrow control on first load
  manageControls(currentPosition);
 
  // Create event listeners for .controls clicks
  $('.control')
    .bind('click', function(){
    // Determine new position
      currentPosition = ($(this).attr('id')=='rightControl') 
    ? currentPosition+1 : currentPosition-1;
  
      // Hide / show controls
      manageControls(currentPosition);
      // Move slideInner using margin-left
      $('#slideInner').animate({
        'marginLeft' : slideWidth*(-currentPosition)
      });
    });
  
  // manageControls: Hides and shows controls depending on currentPosition
  function manageControls(position){
    // Hide left arrow if position is first slide
    if(position==0){ $('#leftControl').hide() }
    else{ $('#leftControl').show() }
    // Hide right arrow if position is last slide
    if(position==numberOfSlides-1){ $('#rightControl').hide() } 
    else{ $('#rightControl').show() }
    } 
  });

Creating some objects

First we initiate some variables at the top of the script that we’ll use throughout the script.

currentPosition will be a number that contains the current position of the slideshow. slideWidth is the width of each .slide div, which is fixed at 560px. I chose to declare an object for the $('.slide') selector to make our code look a bit cleaner, but you can skip this and instead use the full selector ($('.slide')) in your syntax.

Finally, we determine the number of slides in our slideshow using the .length method.

Block 6: Variables and constants

var currentPosition = 0;
var slideWidth = 560;
var slides = $('.slide');
var numberOfSlides = slides.length;

Removing the scroll bar

If our script runs, then our user has JavaScript enabled – so we’ll remove the scroll bar by setting the overflow property of slidesContainer to ‘hidden‘ and this will supersede the overflow:auto declaration in our CSS (see Block 3).

Block 7: Changing CSS overflow property value to hidden

$('#slidesContainer').css('overflow', 'hidden');

Inserting a div in the DOM

We’ll use the margin property to move our slides left and right (more on this later). To do so, we need to create a div that wraps around all of our .slide divs, set to the same width as the total width of all our slides. By adjusting this div’s margin property (later on), we will create the effect of it moving left and right.

Block 8: Inserting #slideInner into the DOM using the .wrapAll() method

slides
  .wrapAll('<div  id="slideInner"></div>')

We also need to set the width of #slideInner, the newly created div, to the total width of all .slide divs.

Block 9: Inserting #slideInner into the DOM using the .wrapAll() method

$('#slideInner').css('width', slideWidth * numberOfSlides);

Styling the Slideshow slides in JavaScript

With JavaScript enabled, we want to float the slides to the left so that they display side by side. We also want to set them to a width of 560px since we won’t have the scroll bar anymore.

We can chain the .css method along with the .wrapAll() method we used in Block 8.

Block 10: Giving .slide divs overflow:hidden CSS property

slides
  .css('overflow', 'hidden')
  .wrapAll('<div  id="slideInner"></div>')

Inserting the controls in the DOM

We insert the controls by manipulating the DOM; this way, users using JavaScript-disabled browsers and screen readers won’t have an invalid HTML structure with controls that take them nowhere, which would be confusing because clicking on them would not work without JavaScript.

We do this using the .prepend() and .append() method which inserts an HTML string inside the selected object/s (in this case, the #slideshow div is selected). The text inside the span elements don’t matter because they were hidden

Block 11: Inserting the controls in the DOM

$('#slideshow')
  .prepend('<span class="control" id="leftControl">Moves left</span>')
  .append('<span class="control" id="rightControl">Moves right</span>');

Managing the left and right arrow controls with a function

To manage our controls, we create a function called manageControls that hides and shows the left and right arrow controls based on the current position of the slideshow.

If it’s on the first slide, we hide the left control because there is no preceding slide. On the last slide, we hide the right control because the user has reached the end of the slideshow. We do this by using the .hide() and .show() jQuery methods that hides/shows the selected DOM element/s that precedes it.

Block 12: the manageControls() function

function  manageControls(position){
  // position==0 is first slide
  if(position==0)  { $('#leftControl').hide(); }
  else { $('#leftControl').show(); }
  
// numberOfSlides-1 is last slides
  if(position==numberOfSlides-1) {  $('#rightControl').hide(); } 
  else { $('#rightControl').show(); }
}       

Call manageControls() on DOM ready

When our first script loads, we should call the manageControls() function once to hide the left arrow control. Calling it is easy, we just pass the currentPosition argument into it which should be 0 initially.

Block 13: calling manageControls() on script load (domready event)

manageControls(currentPosition);

Binding click events to the controls

The final step to the jQuery slideshow script is binding events to the left and right controls. This essentially creates “event listeners” that triggers functions when the user clicks on either the left or right arrow controls.

Block 14: Binding a click event listener to .control class

$('.control').bind('click',  function(){
  // do something when user clicks 
});

Updating the value of currentPosition

When the user clicks on a control, we update the value of the currentPosition variable: if the user clicks on the right arrow control (with the ID of #rightControl) then we add one to our currentPosition; if the user clicks on the left arrow control (with the ID of #lefControl), then we subtract 1 from currentPosition. What you see below is called a ternary operator, which is shorthand for if/else control structures.

Block 15: Ternary operator to set new value of currentPosition

currentPosition = ($(this).attr('id')=='rightControl') 
                  ?  currentPosition+1 : currentPosition-1;

Calling manageControls() after updating currentPosition

After we’ve adjusted the value of currentPosition, we call manageControls() again to hide or show our controls based on our new slide position.

Block 16: Calling manageControls() inside .bind method

manageControls(currentPosition);

Animating the slides

Finally, we move #slideInner to the left or right by animating it’s margin-left CSS property value. The left margin is the negative of the width of our slides multiplied by our current position. For example, if we’re moving to Slide 3, then our left margin is equal to -1120px.

Block 17: Using .animate method to transition margin-left CSS property

$('#slideInner').animate({
  'marginLeft' : slideWidth*(-currentPosition)
});

In summary

In this tutorial, we created a simple slideshow script using solid HTML, CSS, and JavaScript (jQuery). We applied the concept of Progressive Enhancement to ensure that our slideshow widget works without CSS and without JavaScript, making our script web accessible in most browsing scenarios.

Feedback? Questions?

What did you think about this tutorial? Were you confused at any point? Was it the fastest and most efficient way possible? Did you spot errors or points of improvement? Hopefully, this tech tutorial broke things down enough to make it simple to follow! Please share your thoughts in the comments so that we can improve tutorials here on Six Revisions. Additionally, if you have questions, we’d love to help – so don’t be shy!

Related content