Blog (my web musings)

Find out what's interesting me, get tips, advice, and code gems that don't fit elsewhere.


Search Blog


Today I revisit the Responsive CSS3 Any Content Slider, enhancing it with auto-play and start / stop controls (and later, a large touch-toggle with swish "zoom" animation), thanks to a sprinkle of JavaScript.

But first, a recap on the CSS-only version that was covered in an earlier blog post, mainly just as a reminder about usage of the checkbox hack to emulate click events via CSS - that's what gives it functionality without JavaScript, but, I was contacted and asked to make it play slides automatically, so rather than get tied up in longwinded CSS3 animations with complicated timing delays, I turned to JavaScript to do the job.

Foreword

Demos are fully functional in modern browsers and IE10+, with 95% functionality in IE9 and basic fallback for content accessibility in IE7/8 (no frills there folks, just basic bread-and-water-type sustenance).

Adding JavaScript

Looking at the CSS-only version, I could see that the easiest way to auto-play the slides would be with a snippet of JavaScript to activate the radios in sequence. Google came up trumps on a convenient function for that - see this JS Fiddle for a reduced case example.

Now, I have extra radios in my slider - one at the start and one at the end which act as extra control arrows necessary for continuous cycling - so I adapted the function to account for that, plus I added a bit of a workaround to accommodate IE9's differing array length. Here's the outcome (speedy 1 second intervals for comfortable viewing)...

Demo 0 - CSS3 Any Content Slider (JS auto-play):

Demo

This was just the first stage. The lack of controls were obviously a problem, so next I wrote 2 simple JS functions to stop and start the slider again, with the initialisation placed inside startSlider(), and that called onload;

function startSlider(){
    startSlides = setInterval(function(){autoSlider('slider')}, 5000);
    }
function stopSlider(){
    clearInterval(startSlides);
    }
startSlider();

And I added extra play / pause control toggle markup to invoke the same stopSlider() function, and a startSlider() function, onclick;

var stopSliderCtrl = document.getElementById('stop-slider');
var startSliderCtrl = document.getElementById('start-slider');
stopSliderCtrl.onclick = function(){
    stopSlider();
    stopSliderCtrl.style.display = 'none';
    startSliderCtrl.style.display = 'block';
    }
startSliderCtrl.onclick = function(){
    startSlider();
    stopSliderCtrl.style.display = 'block';
    startSliderCtrl.style.display = 'none';
    }

I also invoked the stopSlider() function on of all next/prev control arrows to stop the slider whenever the user interacts with it.

var arrow = document.getElementById('slider-outer').getElementsByTagName('label');
for (var i = 0; i < arrow.length; i++) {
    arrow[i].onclick = function(){
       stopSlider();

       stopSliderCtrl.style.display = 'none';
       startSliderCtrl.style.display = 'block';
       }
    }

This results in a reasonably workable outcome...

Demo 1 - Responsive CSS3 Any Content Slider (with JavaScript auto-play and simple controls)

Demo

You can see in the demo above that I added a simple style switch to the JS, that hides and shows the play and pause control buttons as needed. but I wasn't particularly happy with the turn-out - the style.display additions to the JS, coupled with the extra markup for the controls, left me feeling a little bit... meh. Plus, when I handed the demo to my sister on iPhone, she said that she thought the controls looked cluttered in such a small space - even with her delicate lady-fingers, I could see that usability might be a problem. So, I took this feedback and observation away with me, and thought about how I could improve things.

Note to self... Make interaction easier and incorporate existing "learned" behaviour.

So I turned to something that I know many web users are already familiar with - YouTube - and thought about how I could use that behaviour in my slider. Good thinking, Batman - I would make the whole of the active area clickable, and turn that into the stop/start toggle! :)

Demo 2 - Responsive CSS3 Any Content Slider (with JavaScript auto-play and large touch-toggle):

Demo

I wanted to take the opportunity to reduce the markup (and drop the hacky " || &nbsp; || " pause button) and so looked to use only ONE element as my control toggle. Now, some pretty groovy CSS3 icons have emerged on the web recently, so I hopped over to One Div to see if they had anything there I could use. They did - a neat play and pause icon about 8/9 lines down. So, I snaffled those and popped them in to my next slider test as #toggle div. The new JS toggle function (invoked on the #slider div) switches #toggle div's classes during play and pause states, bringing the appropriate icon in to view at the appropriate time;

var sliderOn = true;
var toggleControl = document.getElementById('toggle');
function toggleSlider(){
    if(sliderOn){
       stopSlider();
       toggleControl.className = '';
       setTimeout(function(){toggleControl.className = 'pause zoom';}, 1);
       } else {
       startSlider();
       sliderOn = true;
       toggleControl.className = '';
       setTimeout(function(){toggleControl.className = 'play zoom';}, 1);
       setTimeout(function(){toggleControl.className = '';}, 3000); // remove icons for IE9
       }
    }
document.getElementById('slider').onclick = function(){toggleSlider();}

Then, to sexy things up even more, I also put a 'zoom' animation on the icons that makes them momentarily visible when the toggle area is clicked/tapped;

.zoom { -webkit-animation:zoom 0.75s both; animation:zoom 0.75s both }
@-webkit-keyframes zoom { 0% { opacity:1 } 100% { opacity:0; -webkit-transform:scale3d(3,3,3); transform:scale3d(3,3,3) } }
@keyframes zoom { 0% { opacity:1 } 100% { opacity:0; -webkit-transform:scale3d(3,3,3); transform:scale3d(3,3,3) } }

No animations in IE9 so there's a bit of CSS in the stylesheet that just keeps the icon opacity really low in that browser, and there's a 3 second timeout in the JavaScript that removes the icons when the slides start playing again.

I'm pleased with how it turned out and am happy that the slider falls back to the CSS-only version when JavaScript is disabled. Please feel free to grab the JS, CSS and HTML from the demos above to customise for your own projects.

Update

If you want to remove the 300ms delay on touch devices, try the SwiftClick script that can be found on this page:

Demo

Notice how everything responds instantly - a tap on an arrow or the active-area play / pause toggle - Nice.