I have an animated idea

Jonathan Snook

We (Dan, Ryan, and myself) launched a small page called "I have a business idea". Check it out, if you haven't already — especially in Chrome or Firefox or Safari. Assuming you have JavaScript turned on (as most of you do), you should see some fun animations as you scroll down the page.

I have to admit that the animations that I had in my head were of a much grander scale but there was a time crunch: the site from design to implementation needed to be pulled off in two days. So how did we do it?

The design idea was to have our man-of-the-hour, Skip, put on the various hats that he'll need to wear to get a new business off the ground. Where do you even begin when you have an idea? We broke it down into a few steps with some helpful links along the way.

The steps were thought of as slides, like a Powerpoint presentation, but clearly better. As the user scrolls from slide to slide, Skip transitions from role to role.

Deciding what slide we're on

The first thing to figure out was what slide the viewer was looking at. This was the easiest part. All slides are the same height and are the same distance apart. We look for the window scroll event and then divide that by the height of a slide (plus its margin).

var slideSize = 700;
var scrollTop = $(document).scrollTop() + 100;
var newSlide = Math.round(scrollTop / slideSize);

The 100 that is being added is the margin at the very top of the page. Now that we know what the current slide is in view, we can change the state of the page and change the state of that slide.

First up is the subtle (or maybe not so subtle) background colour change to match the current slide.

document.body.style.backgroundColor = slides.eq(currentSlide)

We used jQuery to handle the heavy lifting. The slides variable is an array of all our slides. We grab the current slide and then grab the background colour from the slide content. That gets applied to the body. Just like that, the carpet now matches the drapes.

Handling the slide transitions

The next step in setting slide state was handling transitions. A slide comes in from the top or from the bottom. The animations should be different to reflect the different movement. Each slide has three states: the current (or default state), the before state, and the after state.

As we transition the slides, we set the state on those by changing an attribute:

if (oldSlide > currentSlide) {
    oldSlideContent.attr('data-state', 'is-after');
} else {
    oldSlideContent.attr('data-state', 'is-before');

currentSlideContent.attr('data-state', 'is-current');

If the old slide is below (or after) the current slide then it's set to "is-after". If it's above then it's set to "is-before". The current slide is aptly set to "is-current".

Slide CSS

Each slide is then made up of a number of components. If you look at the CSS, it's a little messy but you can see the different components of each slide.

#s4-1 { ... }
#s4-2 { ... }
#s4-3 { ... }

Each of those defines the current (or default) state of each slide. For browsers that don't have JavaScript turned on or don't support CSS transitions and animations, it'll just be the normal static slides. For everybody else, we set the before and after states.

.slide-content[data-state=is-after] #s4-3 { top: 400px; }
.slide-content[data-state=is-before] #s4-3 { top: -200px; }

CSS Transitions do the heavy lifting for us. As we set the state, the browser sees that the top value has changed and transitions that property smoothly over a brief period of time.

Since I knew I was going to be animating a lot of stuff on the page, I just transitioned ALL the things!

* {
    -webkit-transition: all 1s;
    -moz-transition: all 1s;
    -ms-transition: all 1s;
    -o-transition: all 1s;
    transition: all 1s;


We added a few small animations along the way, like the flying money on the last slide. Something fun along the way. First, we defined the keyframes of our animation.

@-moz-keyframes float {
    0% { -moz-transform: rotate(0deg) translate(0,0); }
    30% { -moz-transform: rotate(-20deg) translate(10px,10px); }
    70% { -moz-transform: rotate(20deg) translate(-10px,10px); }
    100% { -moz-transform: rotate(0deg) translate(0,0); }

In this case, the floating money moves the element at different points in the timeline. It rotates and shifts (or translates) the element from its current position.

With the animation keyframes defined, the animation needs to be applied to an element.

#s9-3 {
    -moz-animation: float 8s infinite linear;

The animation is done over 8 seconds to create a nice soft effect and loops infinitely. To have each dollar bill float at a different frequency, we just changed the animation length.

#s9-4 {
    -moz-animation: float 10s infinite linear;

Browser Compatibility

We used a bunch of cutting edge CSS to do this and as a result, we added all the vendor prefixes for the major browsers out there. For browsers that don't support it, it should still show the default state of the slides.


In a way, building this felt like doing animations in Adobe Flash. Elements were laid out on a canvas and then keyframes were defined for each of the elements that we wanted to animate. There are a number of tools, like Adobe Edge, that allow you to create these types of animations in a graphical way without necessarily needing to get your hands dirty with code.