Today CSS animation can be used to progressively enhance websites. The code for my responsive image slider is a popular way of achieving this, but has three potential impediments for developers:
- Developers don’t always remember to add browser vendor prefixes.
There’s a very good argument for automating these actions with JavaScript. The result will animate using CSS in all modern browsers, without having to worry about code, frameworks, plugins or prefixes.
There are just three conditions:
- The images must be placed within an element with an
idofslidy #slidymust be inside a container that hasoverflow: hiddenapplied to it.
The script also has the option of changing the pace of the animation by altering the values of two variables.
Step One
Place the images inside the #slidy element. For this example I’ll use a <figure>:
<div id="slidy-container">
<figure id="slidy">
<img src="eyes.jpg" alt>
<img src="lou.jpg" alt>
<img src="lucielle.jpg" alt>
<img src="lucie.jpg" alt>
</figure>
</div>
I’ve wrapped a <div> around the <figure> to serve as a container.
Step Two
The outer container can be given almost any appearance you wish, so long as it has overflow: hidden placed on it:
#slidy-container {
width: 100%; overflow: hidden;
}
Step Three
Finally, add the JavaScript to the end of the page:
<script>
var timeOnSlide = 3,
timeBetweenSlides = 1,
animationstring = 'animation',
animation = false,
keyframeprefix = '',
domPrefixes = 'Webkit Moz O Khtml'.split(' '),
pfx = '',
slidy = document.getElementById("slidy");
if (slidy.style.animationName !== undefined) { animation = true; }
if ( animation === false ) {
for ( var i = 0; i < domPrefixes.length; i++ ) {
if ( slidy.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
pfx = domPrefixes[ i ];
animationstring = pfx + 'Animation';
keyframeprefix = '-' + pfx.toLowerCase() + '-';
animation = true;
break;
} } }
if ( animation === false ) {
// animate using a JavaScript fallback, if you wish
} else {
var images = slidy.getElementsByTagName("img"),
firstImg = images[0],
imgWrap = firstImg.cloneNode(false);
slidy.appendChild(imgWrap);
var imgCount = images.length,
totalTime = (timeOnSlide + timeBetweenSlides) * (imgCount - 1),
slideRatio = (timeOnSlide / totalTime)*100,
moveRatio = (timeBetweenSlides / totalTime)*100,
basePercentage = 100/imgCount,
position = 0,
css = document.createElement("style");
css.type = "text/css";
css.innerHTML += "#slidy { text-align: left; margin: 0; font-size: 0; position: relative; width: " + (imgCount * 100) + "%; }";
css.innerHTML += "#slidy img { float: left; width: " + basePercentage + "%; }";
css.innerHTML += "@"+keyframeprefix+"keyframes slidy {";
for (i=0;i<(imgCount-1); i++) {
position+= slideRatio;
css.innerHTML += position+"% { left: -"+(i * 100)+"%; }";
position += moveRatio;
css.innerHTML += position+"% { left: -"+((i+1) * 100)+"%; }";
}
css.innerHTML += "}";
css.innerHTML += "#slidy { left: 0%; "+keyframeprefix+"transform: translate3d(0,0,0); "+keyframeprefix+"animation: "+totalTime+"s slidy infinite; }";
document.body.appendChild(css);
}
</script>
I’ve left a fully commented version of the script on CodePen, together with a GitHub repo. The code is responsive in more ways than one: remove an image from inside the #slidy container or add several, and the JavaScript will always create the correct CSS animation to match.
There are two user-defined variables at the very beginning of the script that you can adjust:
timeOnSlideis the amount of time, in seconds, for each image to remain static.timeBetweenSlidesis the time to move from any one slide to the next, also in seconds.
Both variables can take floating point values. For example, timeBetweenSlides = 1.5, will set a one-and-a-half second transition between each image.
Fallbacks
Graceful degradation in older browsers (mostly <IE10) or those blocking JavaScript could be added with a few more lines of CSS:
#slidy { margin: 0; font-size: 0; position: relative; width: 400%; }
#slidy img { width: 25%; }
(This assumes that you have four original images).
The result will be a static, responsive image (the first in the series) without animation.
Photographs by AP Photographie and Konstantin DaCosta, licensed under Creative Commons. Play with this code live on CodePen
Pro CSS3 Animation, Apress, 2013
Massive Head Canon
The New Defaults
CSSslidy