skip to content

CSS: Fading slideshow with a touch of JavaScript

 Tweet0 Shares0 Tweets

Thanks mainly to WordPress, every other website now has some kind of carousel or slideshow on the homepage. That is despite all advice to the contrary.

Regardless of the merits, these features also tend to use bloated JavaScript and jQuery plug-ins adding hundreds of extra kilobytes to the homepage - slowing things down and damaging SEO on the most important page of your website.

Here we present a simple slideshow which by contrast requires less than 1kb of CSS and JavaScript.

Setting up the HTML

The starting point is to set up a list of images on the page, wrapped in a DIV. Something like the following:

<div id="stage"> <a href="1.jpg"><img src="1.jpg" width="360" height="270"></a> <a href="2.jpg"><img src="2.jpg" width="360" height="270"></a> <a href="3.jpg"><img src="3.jpg" width="360" height="270"></a> <a href="4.jpg"><img src="4.jpg" width="360" height="270"></a> <a href="5.jpg"><img src="5.jpg" width="360" height="270"></a> <a href="6.jpg"><img src="6.jpg" width="360" height="270"></a> <a href="7.jpg"><img src="7.jpg" width="360" height="270"></a> <a href="8.jpg"><img src="8.jpg" width="360" height="270"></a> </div>

In this example all the images have links, but that's not necessary. If you remove the links, you'll just need to change some of the CSS and JavaScript to reference 'img' instead of 'a'. Later we'll look at placing text over the images for a caption, call to action (CTA) or similar.

An improvement would be to have only two images on the page load time, and then post-load and insert the others into the DOM as required. That saves having to load them all at once, making the page faster and boosting SEO.

If we stop here, our images are just going to wrap across the page. What we need is some styles to prevent that from happening.

CSS to stack the images

Here is the CSS we are using for the demonstration below:

<style type="text/css"> #stage { margin: 1em auto; width: 382px; height: 292px; } #stage a { position: absolute; } #stage a img { padding: 10px; border: 1px solid #ccc; background: #fff; } #stage a:nth-of-type(1) { animation-name: fader; animation-delay: 4s; animation-duration: 1s; z-index: 20; } #stage a:nth-of-type(2) { z-index: 10; } #stage a:nth-of-type(n+3) { display: none; } @keyframes fader { from { opacity: 1.0; } to { opacity: 0.0; } } </style>

By setting the links to position: absolute we're taking all the images out of the document flow and stacking them on top of one another. We then need to assign a width and height to #stage to reserve space on the page for the slideshow. This equals the image dimensions plus padding (10px on each side) and borders (1px on each side).

We then use some nth-of-type selectors to place the first image on top of the stack, the second image just behind, and the rest hidden from display.

Finally, we assign an animation keyframe to the top image telling it to wait four seconds before fading out to opacity: 0. All that's missing now is a touch of JavaScript to move the faced image to the bottom of stack so the next image can be displayed and fade out in turn.

A touch of JavaScript

All that is needed here is to assign an event handler to our images that is triggered when the keyframe animation ends. It takes the foremost photo, and moves it to the back. Much as you would do with a pack of playing cards:

<script type="text/javascript"> // Original JavaScript code by Chirp Internet: www.chirp.com.au // Please acknowledge use of this code by including this header. document.addEventListener("DOMContentLoaded", function(e) { var stage = document.getElementById("stage"); var fadeComplete = function(e) { stage.appendChild(arr[0]); }; var arr = stage.getElementsByTagName("a"); for(var i=0; i < arr.length; i++) { arr[i].addEventListener("animationend", fadeComplete, false); } }, false); </script>

The new uppermost image now assumes the nth-of-type(1) properties, including the fader keyframe, and so on through the other images.

And that's it! No bloated code, no plugins, no libraries, just a few lines of vanilla JavaScript which works in all modern browsers.

To support older browsers, there are browser prefixes for WebKit, Mozilla and Microsoft and you can find details in our earlier article on constructing an Infinite Animated Photo Wheel.

Working demonstration

Putting it all together you get a simple fading slideshow:

If you want the slideshow to move slower, or faster, or use a different transition, it's just a matter of adjusting the Transition Timing Function (or animation-timing-function in this case). The borders can also be easily re-styled or removed.

Displaying text over the slideshow

There are many ways to go about this, but perhaps the simplest is to add some title attributes to our links and have them displayed over the image using CSS:

#stage a::after { position: absolute; left: 11px; bottom: 11px; padding: 2px 0; width: calc(100% - 22px); background: rgba(0,0,0,0.5); text-align: center; content: attr(title); font-size: 1.1em; color: #fff; }

With no other changes aside from adding titles to our links, we now have the startings of a basic CTA slideshow, which could even be turned into a carousel with a few tweaks to the keyframe.

So if you absolutely have to have a homepage slideshow to please the powers that be, think about ditching jQuery for something like the above. And let us know if you have any feedback or questions using the button below.

Converting to a carousel

A few simple changes to the CSS makes our slideshow behave more like a carousel:

CSS:

<style type="text/css"> #stage { margin: 1em auto; width: 360px; height: 270px; border: 10px solid #000; overflow: hidden; } #stage a { position: relative; display: inline-block; } #stage a::after { position: absolute; top: 50%; left: 0; transform: translateY(-50%); width: 100%; text-align: center; content: attr(title); font-weight: bold; font-size: 2em; color: #fff; text-shadow: -1px -1px 0 #333, 1px -1px 0 #333, -1px 1px 0 #333, 2px 2px 0 #333; } #stage a:nth-of-type(2) { left: 360px; top: -50%; animation-name: slider; animation-delay: 4s; animation-duration: 1s; animation-timing-function: cubic-bezier(0,1.5,0.5,1); } #stage a:nth-of-type(n+3) { display: none; } @keyframes slider { from { transform: translateY(-50%) rotate(30deg); left: 360px; } to { transform: translateY(-50%); left: 0px; } } </style>

JavaScript:

<script type="text/javascript"> // Original JavaScript code by Chirp Internet: www.chirp.com.au // Please acknowledge use of this code by including this header. document.addEventListener("DOMContentLoaded", function(e) { var stage = document.getElementById("stage"); var slideComplete = function(e) { stage.appendChild(arr[0]); }; var arr = stage.getElementsByTagName("a"); for(var i=0; i < arr.length; i++) { arr[i].addEventListener("animationend", slideComplete, false); } }, false); </script>

And of course your first question is going to be how to add navigation spots or arrows over the image...

References

< CSS

Send a message to The Art of Web:


used only for us to reply, and to display your gravatar.

CAPTCHA

<- copy the digits from the image into this box

press <Esc> or click outside this box to close

Post your comment or question
top