Build an Infinite Scrolling Photo Banner With HTML and CSS

by on 3rd April 2012 with 38 Comments


Today we’re going to embark on the challenge of creating an animated banner of photos that automatically scrolls horizontally through an infinite loop. The best part: we’re going to do it without a single line of JavaScript.

To make this banner truly useful, our goal will be to use individual photos dropped into our HTML, not simply one long CSS background that repeats. This is pretty tricky but we’ll walk you through exactly how it works. Let’s get started!

The Idea

The concept here is simple. Let’s say you have a photography website or design portfolio and want a simple banner across a web page that automatically scrolls horizontally through some images like this:


As you can see, we basically just have a strip of images that move their position from left to right. This is a fairly popular technique. In fact, you can see it at work live on Gina Meola’s site.


This effect is easy enough with JavaScript or Flash, but as an exercise let’s see if we can pull it off in pure CSS. With the fancy new tools in CSS3 it’s actually a really easy project that is perfect for anyone looking to dip their toe into CSS animation.


As promised, this is a pretty easy project, but only because I’ve done most of the problem solving for you. In truth, it took me a while to figure out how to pull this off like I wanted. The reason for this is that there’s an easy way and a hard way to do it.

The Easy Way

The easy way is to take the images that you want to display, import them into Photoshop, then combine them into one long image. You can then set this image to your background in CSS, repeat it on the x-axis and toss in a CSS animation.


This works just fine and I was able to get it up and running in only a few minutes, but the problem is that it’s really not a versatile solution. For instance, let’s say I wanted to link each individual image somewhere, this would be impossible if they were in reality all one image. This same logic means that I can’t apply any special hover effects to individual images. Also, if I want to add or swap out images, it requires another trip to Photoshop to update the file. This is definitely not ideal.

The Hard Way

Let’s ditch the easy way because it’s neither a challenge, nor is it really the best method for achieving our goal. The hard way is to actually insert the images one at a time into HTML and have them take on the banner functionality.


The reason that this is so difficult is because we want the animation to be infinite. In CSS, you can easily repeat a background image, but there’s no method for repeating something in HTML. Even if there were, we would only want one image to repeat after all of the others were rendered. As you can see, it’s quite the conundrum.

This is where keyframe animations come to the rescue. The interesting thing about this type of animation is that it will actually step up and take charge of the infinite repetition for us… sort of. It really loops the animation, not the images, but we can use that to create the illusion of infinitely repeating images.

To see how this works, imagine if we just set up a row of images and then used keyframes to animate them. We’ll have a starting point (0%) and a stopping point (100%) like this:


As you can see, this is awkward because it leaves a bunch of unwanted dead space. Further, when the animation starts over, there will be a jarring flash as it goes back to the beginning. We’ll indeed have an infinite animation, but it will look horrible.

If you’re familiar with animation tricks, the solution should be clear already. What we need to do is make our first frame perfectly match our last frame, then when the animation repeats, it will be seamless and will give the illusion of an infinite stream of images.


Unfortunately, to do this, we’ll need to repeat a few images in our HTML. This is sort of a pain but it’s not the end of the world and we only need to repeat enough images to fill the frame.

Let’s Build It

Now that we have the concept worked out, it’s time to code a demo! Let’s start with the basic HTML for our page.


To build a nice demo page, we’ll include a header (use html5shiv for IE) and some filler text, then a div containing our images. Notice that we have six unique images, then the first four are repeated. The initial at least partially shows pieces of these four photos.

Animated Photo Banner

Lorem ipsum dolor...

What’s with that non-semantic “first” class? Basically, to make the animation work, we need to target the first image and move it to the left (the others will follow). This should be easy enough with first-child but targeting pseudo elements and/or pseudo classes for animation is something with spotty support. I couldn’t get it to work in several browsers so I went the old school class route instead. Feel free to riot if you can’t get down with this method.

Starting CSS

To get started with our CSS, throw on a basic margin/padding reset to make sure our images line up properly everywhere. Next, add a dark background texture or color to the body and style the container, taking care to give it a width of 1000px and setting the overflow to hidden.

* {margin: 0; padding: 0;}

body {
	background: url('dark_geometric.png');

#container {
	width: 1000px;
	overflow: hidden;
	margin: 50px auto;
	background: white;

Next we’ll style the header and photobanner sections. For the header, give it a width of 800px so it doesn’t stretch all the way across the container. Also center it with the margin auto trick and apply some basic styles to the text.

For the photo banner section, give it a height of 233px and a width of 3550px. This seems crazy long but it allows the images to all be placed end to end and the container is taking care of our overflow so it won’t create any weird scrolling issues.

header {
	width: 800px;
	margin: 40px auto;

header h1 {
	text-align: center;
	font: 100 60px/1.5 Helvetica, Verdana, sans-serif;

header p {
	font: 100 15px/1.5 Helvetica, Verdana, sans-serif;
	text-align: justify;


.photobanner {
	height: 233px;
	width: 3550px;
	margin-bottom: 80px;

With this code, our demo page looks great. We’ve got a nice little container of content that looks just how we want. The images are static at this point so our next step will be to build the animation.


Bring It To Life

The keyframe animation process is pretty straightforward. To begin, we want to target that “first” class that we created and declare an animation. Here we name the animation, then set a duration and timing duration and set the repetition to infinite.

Moving down the line, we then define our frames using the @keyframes syntax. We only really need two frames here, one to start and one to stop. We simply set the margin to a negative value to move the line of images left far enough that the second iteration of the first image takes the initial spot.

/*keyframe animations*/
.first {
	-webkit-animation: bannermove 30s linear infinite;
	   -moz-animation: bannermove 30s linear infinite;
	    -ms-animation: bannermove 30s linear infinite;
	     -o-animation: bannermove 30s linear infinite;
	        animation: bannermove 30s linear infinite;

@keyframes "bannermove" {
 0% {
    margin-left: 0px;
 100% {
    margin-left: -2125px;


@-moz-keyframes bannermove {
 0% {
   margin-left: 0px;
 100% {
   margin-left: -2125px;


@-webkit-keyframes "bannermove" {
 0% {
   margin-left: 0px;
 100% {
   margin-left: -2125px;


@-ms-keyframes "bannermove" {
 0% {
   margin-left: 0px;
 100% {
   margin-left: -2125px;


@-o-keyframes "bannermove" {
 0% {
   margin-left: 0px;
 100% {
   margin-left: -2125px;


That’s all there is to it! With this code, your banner of images will begin its infinite loop through the six photos that we included.

Taking It Further


To really showcase the benefits of this method, I decided to go a step further and add in a simple hover effect for each image. This would’ve been impossible with the CSS background technique. On hover, we’ll scale the image by 20% and add a shadow.

.photobanner {
	height: 233px;
	width: 3550px;
	margin-bottom: 80px;

.photobanner img {
	-webkit-transition: all 0.5s ease;
	-moz-transition: all 0.5s ease;
	-o-transition: all 0.5s ease;
	-ms-transition: all 0.5s ease;
	transition: all 0.5s ease;

.photobanner img:hover {
	-webkit-transform: scale(1.1);
	-moz-transform: scale(1.1);
	-o-transform: scale(1.1);
	-ms-transform: scale(1.1);
	transform: scale(1.1);
	cursor: pointer;

	-webkit-box-shadow: 0px 3px 5px rgba(0,0,0,0.2);
	-moz-box-shadow: 0px 3px 5px rgba(0,0,0,0.2);
	box-shadow: 0px 3px 5px rgba(0,0,0,0.2);


We’re all finished! Click here or on the image below to see the live version.



We had a difficult goal at the beginning of this article. We wanted to create an infinitely scrolling banner of images using pure CSS. The biggest challenge here was how to get a bunch of HTML images to repeat. The trick of course was to set up a keyframe animation while making sure that our first and last frames matched perfectly. This allowed us to seamlessly loop the animation.

Leave a comment below and let us know what you think of this effect. How would you change or improve upon it?

Comments & Discussion


  • verpixelt

    thx for this rly rly nice tutorial. Theres just one point i cant deal with. The gallery is juddering while moving. I tried to solve it with slowing it down but its still happening. I tested it on windows 7 in ff/chrome and safari.

  • ChrisB

    > Unfortunately, to do this, we’ll need to repeat a few images in our HTML.

    I think adding a few elements to the end of the list via :after/content should also work – actually inserting these images as backgrounds, although that would mean to provide the URIs and element dimensions separately as well …

  • Luchs

    You forgot the Opera vendor prefix in .first.

  • CJ

    First, thank you for the nice tutorial. I am a newbie at wordpress, so forgive me if this is a dumb question.

    I noticed that when I clicked on the Gina Meola site her gallery was responsive and adjusted when sized down. When I clicked on the demo above it was not responsive when sized down. Do you know what was done differently on her site to give it the responsive design? I love the scroll gallery and would love it even more if I was able to make it responsive ;)

  • Luis Paulo Lohmann

    Nice exercise! I liked it very much.

    @CJ, Gina’s website isn’t made like this tutorial. It’s a flash website used just to illustrate what’s this tutorial is trying to achieve.

    Although, I’m pretty sure a responsive version of this tutorial could be made.

  • dana

    I really like the look of the moving banner and great that it requires html and css only.
    But when I checked my files against “CSE HTML” the coding was not accepted as permissible.
    ‘animation property is not a recognized style property’ was one note, and ‘the at (@) rules will be ignored’ was another.
    Do you know how I can make this “legal”, I’d really like to keep it and stay within the rules? Thanks.

  • dk

    Joshua, thanks for the article. Will enjoy working with this project. How would one have this layered behind front layer of text or artwork, where the text might be the Website Title for example, which would act like Geola’s front layered static artwork in the upper left corner of her site?

  • Becky

    Excellent tutorial – thank you!

    This works perfectly in Firefox and Chrome but will do NOTHING in Internet Explorer.

    Is this common/typical or did I miss something?

  • Bobby

    Wonderful. thx for the tutorial.

  • JB

    Fantastic tut, thank you. Only apparent issue is a lack of IE compatibility, unless as Becky says, I’ve missed something.

  • Andrei

    Superb. But it doesn’t work on IE.
    Can someone post a fix?

  • Julian

    Yes, can someone post a fix for IE

    • Karen

      Did you figure out a workaround? It doesn’t work in Firefox on my computer either. Otherwise works great in Chrome.

  • joe

    Thanks for the post was a great example. However would really appreciate if you had a IE fix for this i have tried and tried anything and everything I know with no results. I think it would help various others who have posted same request. Thanks Again

  • Patrick

    Do you guys know if there is anyway to achieve a similar effect while linking the photos to an RSS feed, flickr.

  • Gary

    Thanks so much for this tutorial, Josh. While it wasn’t a “cut and paste” effort, I was able to tweak the code to fit my needs (47 photos on a 860 px outer wrapper). The result isn’t perfect since I was too tired to try to figure out the math for the appropriate container size but it certainly satisfied my need.

  • Lenka

    Thank you for the tutorial Josh, really nice effect.
    Does anyone know how do I get rid of the ‘white’ space between the photos? I would like to have them next to each other… Can’t figure out how to fix that. Any help would be much appreciated. Thanks.

  • Lenka

    Could anyone explain the maths behind? I am completely lost. How and what values should I change if I use bigger/wider images? Would be grateful for any advice. Thanks in advance.

  • Gretchen

    Thanks for the tutorial! I would great appreciate an explanation of why it is not IE compatible and how to make it compatible. Thanks again for your time and detailed instruction!

  • Bob

    Works great on a test page I made, how would I use a folder contents instead of listing images in the HTML ??

  • Leona

    Thank you this was what I needed! :)
    I am however, having problems. my last two pictures won’t show in the photo banner. It gets cut off. Help please? :(

  • Mattyc

    This was a very thorough and well laid out tutorial. Thank you for you knowledge and work.

    I’m trying to add this to a site and i’m not getting any scrolling. the images appear, the hover effect works beautifully but the pictures aren’t scrolling. I’ve checked it in all of the browsers i currently have installed, IE, firefox, chrome, opera & safari. Can you give me an idea where to look to figure out there my mistake was likely made, please?


  • yourfriend

    Thanks provider. This really helped me thatnking you

  • suleman

    nice article. it help me very.

  • dhananjay

    current setting i tried but not working

  • Pumpkintje

    Nice tutorial!
    But I have 2 errors:
    – ‘property animations doesn’t exist’
    – @ keyframes not implemented

    Can anyone help me? Or did I miss something?

  • Balanced Designer

    I have a question: How to make this tutorial work with hyperlinks. I tried to put a hyperlink on one of my images and it breaks the scroll. Any suggestions?

    By the way, GREAT tutorial.



  • smiti

    my banner is not moving
    everything else isworking fine
    can u plz alpha

  • Sean

    Anyway to make the image automatically scale when it reaches the center of the div instead of the hover action?

  • Jasmeet Singh


  • Yoram

    I tried to change the dimentions so that image width is 100px and I figured I should make the photobanner a little more than 1000px to keep the proportions you had. It left a huge blank gap in the photo chain though unitl it reset to the beginining. Do you know why?

  • Chloe

    So the banner scrolls in Mozilla Firefox, Google Chrome and Opera. It does not scroll in Internet Explorer for me. Does anyone know how to go about fixing that?

    • Chris Thomas


      Did you uncomment this line:


  • Chris Thomas

    I tried to copy and paste and it works, yet when I add more images to the code it loops after just a few (i.e. I add 30 images to the code, it starts over after only 7 instead of the original 10)

  • Chloe Williams-Healy

    The pictures wouldn’t line up horizontally like you had them. They just stacked themselves right on top of each other.

  • Carlos

    Hello All, Thank you for this great tutorial! How can I make this work on IE 8?

  • cordless hammer drill reviews

    I love what yyou guys aree up too. Such clever work and exposure!Keep
    up the awesome works guys I’ve incorporated yoou guys to ourr blogroll.


About the Author