Pure CSS and JavaScript slideshow

Pure CSS and JavaScript slideshow

Look, ma: no jQuery! A simple JavaScript slideshow with CSS3 transitions.

Sometimes it's preferable to use an old-fashioned approach to create JavaScript slideshows without the aid of a powerful library such as jQuery but only with the newly introduced CSS3 features, namely transitions and animations. Let's see this example.

We have this canonical HTML structure:


<div id="slideshow">
    <div id="slideshow-wrapper">
        <img src="1.jpg" alt=""/>
        <img src="2.jpg" alt=""/>
        <img src="3.jpg" alt=""/>
        <img src="4.jpg" alt=""/>
        <img src="5.jpg" alt=""/>
    </div>
    <div id="slideshow-nav"></div>
</div>

Our images will be stacked one on the top of the other. By doing so, we need to dynamically adjust their opacity and z-index to show one image per time. We're going to use CSS transitions for our purpose:


#slideshow {
    margin: 2em auto;
    width: 400px;
    overflow: hidden;
}

#slideshow-wrapper {
    height: 220px;
    width: 400px;
}

#slideshow-wrapper img {
 	position: absolute;
    width: 400px;
    height: 220px;
    opacity: 0;
    -moz-transition: all 800ms ease-in;
    -webkit-transition: all 800ms ease-in;
    -o-transition: all 800ms ease-in;
    -ms-transition: all 800ms ease-in;
     transition: all 800ms ease-in;
     z-index: 1;
}

#slideshow-wrapper > img:first-child {
    opacity: 1;
    z-index: 2;
}

#slideshow-wrapper .show {
	opacity: 1;
	z-index: 3;
}

#slideshow-wrapper .hide {
	opacity: 0;
	z-index: 1;
}

#slideshow-nav {
    height: 32px;
    margin: 1em 0;
    text-align: center;
}

#slideshow-nav a {
    display: inline-block;
    width: 32px;
    height: 32px;
    line-height: 32px;
    text-decoration: none;
    text-align: center;
    color: #fff;
    background: #a00;
    margin-right: 1em;
}​

The show and hide CSS classes will be added or removed via JavaScript. Coming to JavaScript, we need to define an object where we can store the logic behind our slideshow:


var Slideshow = {
	//...
};

Now we need three utility methods:

  1. a method to collect all the siblings element of the current image
  2. a method to hide elements
  3. a method to show elements

Utils: {
	siblings: function(element) {
		var parent = element.parentNode,
			childs = parent.childNodes,
			sibls = [],
			len = childs.length,
			i;
		for (i = 0; i < len; i++) {
			var child = childs[i];
			if (child.nodeType == 1 && child.tagName.toLowerCase() == 'img' && child !== element) {
				sibls.push(child);
			}
		}
		return sibls;
	},
	hideAll: function(elements) {
		var len = elements.length,
			i;
		for (i = 0; i < len; i++) {
			var element = elements[i];
			element.className = 'hide';
		}
	},
	show: function(element) {
		element.className = 'show';
	}
}

Then we have to define the core of our object. The first method will create the navigation links which have a custom data attribute corresponding to the DOM index of each image. The second method will attach an event handler to each navigation link:


core: {
	displayNavigation: function() {
		var images = document.getElementById('slideshow-wrapper').getElementsByTagName('img'),
			len = images.length,
			i, nav = document.getElementById('slideshow-nav'),
			html = '';
		for (i = 0; i < len; i++) {
			html += '<a href="#" data-img="' + i + '">' + (i + 1) + '</a>';
		}
		nav.innerHTML = html;
	},
	navigate: function() {
		var links = document.getElementById('slideshow-nav').getElementsByTagName('a'),
			len = links.length,
			i;
		for (i = 0; i < len; i++) {
			var a = links[i];
			a.onclick = function() {
				var $i = this.getAttribute('data-img');
				var img = document.getElementById('slideshow-wrapper').getElementsByTagName('img')[$i];
				Slideshow.Utils.show(img);
				var siblings = Slideshow.Utils.siblings(img);
				Slideshow.Utils.hideAll(siblings);
				return false;
			};
		}
	}
}

Finally we have to define an initialization method:


init: function() {
	for (var prop in this.core) {
		if (typeof this.core[prop] === 'function') {
			this.core[prop]();
		}
	}
}

The last step is to kick things off:


Slideshow.init();

[view-example url="http://jsfiddle.net/gabrieleromanato/ds8Gy/"]