Just for kicks I wanted to see if I could make a row of images animate across a page and repeat indefinitely. Turns out it’s really not that hard.

See the Pen Infinite Slideshow by Chris Coyier (@chriscoyier) on CodePen.
The concept is to move the position of the long graphic
First the graphic should be designed such that there is a portion of it that repeats. Then you animate the left position of that image until it appears it’s completed one full cycle (but really is just moved far enough to look identical), then it quickly warps back to the original position and starts over.
We just need an outer wrapper to be relative positioned and hide the overflow, then an inside container in which to animate (which is the image).
<div class="slideshow">
<div class="images">
A slideshow of images in here (whatever you want to say for screen readers)
</div>
</div>
.slideshow {
position: relative;
overflow: hidden;
}
.images {
background: url(slideshow.jpg);
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 300%;
animation: slideshow 10s linear infinite;
}
@keyframes slideshow {
0% { left: 0; }
100% { left: -200%; }
}
Let’s squeeze some better performance out of this thing, cowboy.
The above code should work fine, but it might be a little choppy depending on the browser/platform/version/resources available. We can get better performance (at least in WebKit / Mobile WebKit) by telling the browser we are going to be using 3D transforms (even though we aren’t) and then using translateX
instead of left
.
NOTE: This trick specifically increases the performance (that you normally wouldn’t get) out of 2D transforms and opacity changes. If we weren’t changing over to using translateX
, we wouldn’t see any benefit.
.images {
...
/* Hey browser, use your GPU */
transform: translate3d(0, 0, 0);
}
@keyframes moveSlideshow {
100% {
-webkit-transform: translateX(-200%);
}
}
I’m not a huge fan of the fact that we essentially need to trick the browser into better performance, but as CSS folks I guess we’re used to that kind of thing. I think the original way we wrote it is fine and the browser should recognize when it can be more performant and do that.
Adding Fancies
With my slideshow, I wanted to do two additional cool effects beyond just scrolling the images by. When you rolled over the slideshow it would:
- Speed up
- Change from black & white to color
To speed it up, you might just think, we’ll just reduce the duration on hover! And thus:
.slideshow:hover .images {
animation-duration: 5s;
}
But this is going to be jerky! By changing the animation duration you create a new timeline of what properties should be at what values and when. It figures out those new values and jumps to where they should be immediately. It does not just “speed up” from it’s exact current position. I’m afraid I don’t know a really solid way around this.
Instead, we’ll just adjust the concept of “speeding up”. If we set two slideshows on top of each other, each one running at different speeds, then hide/show the top-most faster-running on on hover, we can get a pretty decent “speeding up” effect. We’ll use transitions to make the transition smoother.
<div class="slideshow">
<div class="images-1">
A slideshow of images in here (whatever you want to say for screen readers)
</div>
<div class="images-2">
</div>
</div>
.slideshow > div {
...
transition: opacity 0.5s ease-out;
/* Slow */
animation: moveSlideshow 60s linear infinite;
...
}
.images-1 {
/* Fast */
animation: moveSlideshow 20s linear infinite;
}
.slideshow:hover .images-2 {
opacity: 0;
}
For the black and white thing, what we’ll just make the top-most slideshow black and white and the lower/faster slideshow color. To save an HTTP Request, we’ll make both of them the same image, and just shift the background position.

.images-1 {
/* Sprite */
background-position: 0 200px;
...
}
So that should do it!
See the Pen Infinite Slideshow by Chris Coyier (@chriscoyier) on CodePen.
Origin
This idea came the Wufoo Hearts Tech Events page we recently did, where I wanted to show off images from several of the events we’ve been at recently. And, admittedly, I just wanted to play with this idea.
First off – this is really nice CSS-work.
Excuse me if this sounds dense; but I see all this animation being moved from JS to CSS but it just feels to me like people are doing because they can, not that it’s necessarily an improvement.
I compare this code to something similar I wrote in JS and can’t help but think how much easier it is to troubleshoot, tweak, and moreover – just to build in general. Plus, isn’t JS around specifically for this sort of thing?
Again, really nice work, but could someone possibly go into detail about why this is a beneficial way to do things? I’m just not seeing it.
That’s an interesting discussion to start.
I’d argue the other side, in that CSS is for stuff like this and JS is not.
In the classic conversation of “separation of concerns”, CSS is for design/styling and JS is for behavior. An animation is, if you ask me, far more a part of design/styling than it is behavior. It depends on the use of the animation though. A slideshow is pretty gray-area since there is plenty of behavior that can go along with them.
The other thing to discuss is HOW the animation is accomplished. To animate something with JavaScript, you need to rapidly manipulate inline styles on an element. I’d say this is closer to a clever hack than an appropriate way to handle animation. As shown in this tutorial, by making animation happen in CSS, we can actually get the GPU (graphics processor unit) involved and have it handle the animation. That is almost inarguably more efficient than JavaScript =)
Definitely a good point.
Although, I see a few benefits in using CSS sprite scrolls like this.
– it could be good for those that aren’t very fluent in javascript.
– this could be beneficial if the platform that the site is built on doesn’t allow for javascript or the appendage of JS libraries like JQuery or MooTools.
I’ve ran into those kind of instances so this may come in handy in the case it does.
But yes, if it was me, I would do it in JS :)
Either way, well done CC.
Thanks, the clarification about the GPU’s involvement helps a lot.
I guess I see the point of using CSS for stuff that is “animation”, I think it’s the interaction that I get hung up on when I see examples like this.
Probably best to weigh every case when choosing between CSS & JS, but I guess that’s a general rule for any development. I’d love to find a post going into more detail re. this subject since it seems to be gaining momentum.
Chris Coyier – As usual another awesome insight in new use of CSS (transitions).
But I’d like to add a note about GPU use. IE9 uses GPU acceleration for Javascipt animations as well. So it’s not only CSS3 animations that will benefit from GPU acceleration in the future.
<marquee>?
Maybe. Make a demo.
I was watching the slideshow in the fiddle Chris provided and something wasn’t right. I sat and watched a few times and took me ages to realise what was up.
The repeated section of the image is a pixel above the original section.
I then spent a few moments looking for the erroneous code. I felt so stupid when it struck me that the duplicated section is within the image. It is likely a quick copy issue within Photoshop so Chris could provide the demo!
Yes that’s me in the corner, with the Dunce hat!!! :-s
No it’s cool you even caught that. The image in the finished demo has that fixed.
Neat, now can you make controls for it? Maybe have js edit the style sheet on the fly?
Also, when you hover over it, the fast slide is usually in a different place then the slow one, making it appear to change pictures when you hover over it, then change back once you move your mouse back. Is their any solution to this?
I would’ve liked it if you did a bit more canvas magic there. I think Jeffrey Way has a tutorial on how to make a grey scale version of an image using canvas. In your case, the footprint of the tiny bit of JavaScript used to achieve that should be way lower than this sprite image with two colors. Here’s the link: http://net.tutsplus.com/tutorials/javascript-ajax/how-to-transition-an-image-from-bw-to-color-with-canvas/
Very nice!
What about starting to include only CSS3 properties in code snippets? That would make them much easier to read. I’d think by now most people know how to add prefixes, no?
For example, it could be:
/* add prefixed properties here (-webkit-, -moz-, -ms-) and do not forget -o- or @divya will hunt you down :) */
transform: translateX(-200%);
Rather than:
-webkit-transform: translateX(-200%);
-moz-transform: translateX(-200%);
-ms-transform: translateX(-200%);
-o-transform: translateX(-200%);
transform: translateX(-200%);
At this exact time, I prefer listing out all the vendor prefixes. It gives people reading it exactly what they need. If they were forced to add them themselves, they would probably learn better, but I think more people would not do it and be confused/frustrated or just have it be broken. Maybe in a year from now or so the atmosphere around this stuff might be different and I’ll change my mind.
See this really good point below also.
lol. And that’s where I lifted the snippet :-)
Nice catch Ixolite!
Very cool thing to do. I am currently using this on my portfolio site with a little x & y fun.
I assume this can be done with just placing the images inside the HTML as well, rather than animating that background image. (It looks like it has been done like that in this demo).
Then you can actually use it as a sufficient portfolio/featured slider. :)
Just a quickie, am I missing something or there is no point in adding non-webkit transform properties inside of @-webkit-keyframes ?
Ha, yeah, uhmmmm, good point. I fixed that.
Hahaha :p
Cool Work!
With CSS3 you can get really amazing effects!
I’ve always figured there can be a easier way to do a slider with just css. However not working in many browsers is a bummer. Is there anyway to use Modernizr to make it work in those that do not?
modernizr see if it works , it doesnt correct the problem.. so if it is ie8 you have to use jquery or something to solve the problem because css3 not supported.
Nice work!
It’s awesome that we can make a slideshow just with CSS. Who imagined this ten years ago?
The overlay image doesn’t line up? i.e. the colour one. Other than that it’s cool!
Fantastic to be able to do this with CSS. It does seem to be just a little laggy (ie it will scroll for a few seconds and then pause for a few ms) on my desktop. Is anyone else seeing this, or is my desktop slow? Anyhow, its only a very small point.
/Brian
Maybe, the change from the ‘slower’ timeline to the ‘faster’ timeline can be ‘transitioned’ to avoid the ‘jerk’. The
animation-duration
, can it be transitioned/animated from a lower value to a higher value?Can the above ‘transitioning’
animation-duration
be done with CSS3, or would it require resorting to JavaScript?Very cool CSS trick. I enjoyed it and thank you for sharing.
Chris… It’s interesting to watch you and see what things catch your interest. This solution is pretty out of the box and interesting. What could be done about the images not aligning following a (or several) hovers? Anything?
Very cool, thanks for sharing!
Is it just my machine or does this not work in IE9?
In FF6/Win7, hovering over the slideshow causes a different portion of the image to show as colored. It’s not even close (e.g., often the B&W center of the image isn’t even shown during the color hover). Very disconcerting, almost felt like the color images were unrelated to the b&w even though i knew they weren’t.
Amazing stuff:)
Thanks a lot
Came here from Smashing Mag’s twitter and having the same issue as a few other commenters have written – the colour version of the slideshow isn’t synched with the black and white version.
Using Firefox beta 7.0, its clear both the colour and b/w versions are continuously being scrolled at their individual speeds regardless of which is currently displayed to the viewer. Screenie if it helps: http://www.damienking.net/slideshow.jpg
Have to say, its a good use of CSS – inspiring me to delve deeper into what could be possible with CSS alone.
I mention that problem in the article. That is the correct behavior via the spec, and I’m not sure how to have it feel more like it’s speeding up. There may not be a practical way (or there may be, feel free to dig in to it!)
Using ‘ease’ in the webkit animation instead of ‘linear’ has the interesting effect of gently slowing the animation for the last/first frame. This could be desirable if you wanted to give a visual emphasis to that particular image in the set.
Given Demo not working in ie6
Hello, this is a really great article but I can’t understand the trick.
Which part of the code do this “then it quickly warps back to the original position and starts over.”?
Because when I edit the jsfiddle and set 100% { left: -2000%; } to accelerate the process, at some point the image disappear!
Ok, so nobody has understood the trick…
cool things, Thanks for get us some nice feature and idea to build imagination. WELL DONE,
anyway i just try to get text instead of image like paragraph or h2 or others, ummmh let me do that
I’m new to web designing!!
I need a help. I want to have two slideshows with a logo image in middle.
i have this code–” http://jsfiddle.net/chriscoyier/Hyg3C/1/ “please help me out to insert my logo in middle and move one sildeshow to left and other sildeshow to right. As in this website “http://www.mosa.nl/en/”. thanks in advance..
i want to scroll bottom to up how i can do?
how can i scroll it verticaly?
what if one want to add link on mouse hover?
This doesn’t work in IE, and I know that it’s from 2011 but here’s the fix (jsfiddle)
Hey, awesome Joe! Any ideas on how to get the roll over to work? I haven’t had any success so far…
Got it figured out.