Build Your Own Responsive Content Slider Without JS Dependence

In conjunction with a responsive grid system, such as The Organic Grid, creating a responsive content slider is a snap. There are a couple widely used methods to build a content slider which typically involve a containing element styled by an overflow: hidden; CSS declaration. This container serves as a window to mask the "non-active" slides. This tutorial uses a different approach made possible by the CSS :target pseudo class selector. Our goals are outlined as follows:

  • Progressive enhancement
  • Responsive slider that adapts to viewport size
  • Slides capable of containing images or HTML
  • Scalable
  • Easy to use
  • Default slide (when their is not :target url fragment)
  • Integrate with a free jQuery Plugin that is well documented and supported
  • Slides viewed not part of browser history (with JS enabled)

Progressive Enhancement

We firmly believe in web standards and progressive enhancement. This keeps our future-selves sane and helps out anyone else who either works with or inherits our code. Even though relatively few of us browse the internet with Javascript unavailable or disabled there are several key reasons to create fallback measure that accomodate those without Javascript ... mainly, for those who are not human, meaning screen readers for those with disablities as well as for SEO.

Search engine robots, like GoogleBot, do not index certain content like Flash or Javascript as readily as HTML. Creating the content first, then enhancing the user experience with unobstrusive Javascript is a good idea to make sure your content is getting indexed and crawled (and validated) properly. We have seen many designers neglect to use alt text that properly describes images, even though this is a W3C required attribute.

Separation Of Concerns

We are conscious of the Separation of Concerns. In our opinion, animation falls more into the behavioral "layer" of the web which implies Javascript should handle this (as opposed to the CSS presentation layer). But I suppose you could make a case for CSS handling animation and it is wise to stay atop of evolving technologies. The pure CSS animation is accomplished using keyframes, see the references section below for links to a few outstanding tutorials that teach and showcase CSS animations.

HTML

This code uses a custom grid system we developed, for more information read how we developed a responsive grid system. If you do not want to use a grid you may need to include additional rules to constrain the images and their containing element. It is possible to reduce the "div-itis" that grid system can suffer from by creating more semantic markup via LESS.


<div class="row">
	<div class="col-12">

		<div class="slider flexslider">
			<ul class="slides">
				<li id="slide-01">
					<img src="assets/img/slide-01.jpg" alt="Slide 01 Description">
				</li>
				<li id="slide-02">
					<img src="assets/img/slide-02.jpg" alt="Slide 02 Description">
					<span class="temp">My Caption</span></li>
				</li>
				<li id="slide-04">
					<img src="assets/img/slide-blank.jpg" alt="Slide 03 Description">
					<span class="temp">My Other Caption</span>
				</li>
				<li id="slide-03">
					<img src="assets/img/slide-03.jpg" alt="Slide 04 Description">
					<p class="flex-caption">Winning combination.</p>
				</li>
			</ul>
		</div>

	</div><!-- /.col-12 -->
</div><!-- /.row -->

<div class="row">
	<div class="col-12">

		<div class="pager">
			<ul>
				<li><a href="#slide-01"></a></li>
				<li><a href="#slide-02"></a></li>
				<li><a href="#slide-04"></a></li>
				<li><a href="#slide-03"></a></li>
			</ul>
		</div>

	</div><!-- /.col-12 -->
</div><!-- /.row -->

CSS (Via LESS)

Using newer CSS combinators we improve our ability to target elements with more Javscript-like precision to make the pure CSS and HTML slider function.

The core of the styling is founded on hiding the <li> elements, except for the default slide (the last list item in the markup) and active slide.

The min-height is not required if you are only displaying images, but because the slider can handle other HTML, such as blocks of text, it may be best to set a minimum height that can be used in media queries to keep the image and non-image content the same height so the elements below the slider do not shift vertically when the slide heights would otherwise vary. Alternatively, you could create a blank transparent slide as a place holder. HTML elements could then be floated into their place to overlay the pseudo-slide image.


@pagerHeight: 25px;
@slideMinHeight: 125px; // mobile viewport

.slider {
  width: 100%;
  background: #ccc;
  min-height: @slideMinHeight; // fine tune in mqs

  ul {
    padding: 0;
    margin: 0;
    list-style-type: none;
    width: 100%;

    li {
      width: 100%;
      display: none;
    }
    li:last-of-type {
      display: block;
    }
    li:target {
      display: block;
    }
    li:target ~ li:last-of-type {
      display: none;
    }
    li#slide-04 {
      background: #f7f7f7;
      width: 100%;
    }
  }
  img {
    display: block;
    width: 100%;
  }
}

.pager {

  ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    text-align: center;

    li {
      display: inline-block;
      text-align: center;
      margin: 0 .1em;
      padding: 0;
      width: @pagerHeight;
      height: @pagerHeight;

      a {
        background: #888;
        outline: 0;
        display: inline-block;
        width: 100%;
        height: 100%;
        .gradient(#ccc, #777);
        .box-shadow(inset .01 * @pagerHeight .05 * @pagerHeight .1 * @pagerHeight #777);
        .border-radius(@pagerHeight);
      }
      a.active {
        .gradient(#ccc, #aaa) !important;
      }
    }
  }
}

Javascript (Via jQuery)

With the HTML and CSS laid out, we can now enhance the slider with Javascript. Not wanting to re-invent the wheel we decided to implement the Flexslider jQuery Plugin from WooThemes. Flexslider it is easy to use, includes key options, has decent documentation and it is free!

Flexslider is used to enhance the slideshow to add "auto play" functionality and transition effects (fade or slide). The slider also supports swipe getures, as well as keyboard and mouse wheel options to control the slides. The jQuery selector used here is window, as opposed to the typical document object. We have configured Flexslider to use our navigation, however, you can use the slider's built in (default) functionality too. Our navigation needs to function without Javascript, so it makes sense to reuse what we have already written and to make styling the navigation buttons easier with CSS.


$(window).ready(function() {

  $('.flexslider')
    .removeClass('slider')
    .flexslider({
      animation: "fade",
      slideDirection: "horizontal",
      slideshow: true,
      slideshowSpeed: 5000,
      animationDuration: 900,
      directionNav: false,
      controlNav: true,
      keyboardNav: true,
      mousewheel: false,
      prevText: "Previous",
      nextText: "Next",
      pausePlay: false,
      pauseText: 'Pause',
      playText: 'Play',
      randomize: false,
      slideToStart: 0,
      animationLoop: true,
      pauseOnAction: true,
      pauseOnHover: true,
      controlsContainer: ".pager",
      manualControls: "ul li a",
      start: function(){},
      before: function(){},
      after: function(){},
      end: function(){}
  });

});

Gotchas

We had difficultly particularly because sorting out the scope of the General Sibling Combinator. The conclusion we arrived at was to move the default slide to the end of unordered list as :target ~ element will not grab preceding elements (it only finds suceeding elements in the document flow from what we understand). This was necessary for our solution to hide the default slide.

Pay attention when using fluid layouts where the layout width can expand beyond that of the actual image width, as the image can keep expanding and will lose resolution. Extremely large view ports are not our target audience, but the slider can either by constrained by the grid system (column width), Javascript or a CSS media query if need be. It is also possible to have a hybrid layout were portions use the fixed grid and other portions use the fluid grid. In this case, the slider could be put in a fixed grid while the remaining content could be put into the fluid system. Regardless, all images should be optimized to reduce file size, thereby improving page load speed especially since so many users access the web on mobile devices when they are in a rush or have limited data usage. Google also uses page load speed in their ranking algorithm.

Also worth mentioning is the descendant selectors used to style the slideshow may be overkill and it is probably better to only be as specific as necessary. For example, you don't need to target an anchor using .pager ul li a as .pager a would suffice (we wrote it this way to convey the DOM hierarchy).

Extending The Slider

The concepts presented here should allow for the creation of "tabbed" content as well. This is a great way to recycle available page real-estate that will function with or without Javascript.

The Organic Grid System was also modified to include appending and prepending classes that add leading and trailing whitespace to a grid column by adding left and right padding respectively. For example, this is useful to create a smaller content slider that is centered on the page, by adding the classes col-8 prepend-2 append-2 (in our example).

It is also probably a good idea to help out older browsers using something like Modernizr to support to HTML5 and CSS3.

Live Demo and Source Code Download

The outcome of this tutorial can be seen in our live demo and the source code is available for download. To understand what has been built, resize your browser window using a laptop or desktop computer (for each demo). Also, try disabling javascript to see how the slider still functions without the autoplay and fade effects. The code may be updated periodically and slightly differ from what is presented in this article, so be sure to check the source if you have any questions. Let us know if you implement these techniques in your upcoming project! Thanks for reading.

Respect and Resources

  • WooThemes Flexslider
    One of the hundreds or thousands of slideshows or content sliders out there. We have put many hours of research into finding a great slider that does what we are after with little effort. We have used many sliders before, most notably the jQuery Cycle Plugin, but in the end we choose Flexslider for it's simplicity and focus on responsive design.
  • Joshua Johnson at Design Shack wrote Build a Pure CSS Slideshow With Webkit Keyframes
    This site is awesome and a great source of inspiration. This particular tutorial uses CSS3 Keyframes to animate the slideshow which is interesting, but not widely supported by all modern browsers.
  • Another article written by Joshua What's the Deal With :Target in CSS?
    This article helped found the technique used in our tutorial.
  • Harry Roberts at CSS Wizardry wrote Fully fluid, responsive CSS carousel
    Nice (responsive) site with useful information conveyed using succsinct explanations. We dig it. This tutorial has a nice visual of the magic CSS hidden pane "wrapper". The photos credited to Suze in the demo are pretty solid too. Nice work.
  • Robert McIntosh's Pure CSS3 Slideshow
    Great example of the Ken Burns effect that really showcases the new(er) power of CSS.
  • Alessio Atzeni wrote A Pure CSS3 Cycling Slideshow for Smashing Magazine
    This comprehensive tutorial includes animation, progress bar, pausing and tooltips.
  • Jeffrey Way instructs us about The 30 CSS Selectors You Must Memorize
    Another great reference from Nettuts, as usual this article does not dissappoint. A good bookmark.