menu

CSS3 Tricks - Creating Beautiful Animated Sceneries Using Only CSS

Posted Aug 31, 2012 by Mathieu Chiasson


Today's little CSS3 trick is a very cool one. It's uses? Well you'll need a web site with a lot of personality to use this but if you do, your visitors are going to be in for a nice treat!

We'll create a fully animated sky with clouds soaring with the wind and a dancing sun. Excited? I bet you are!

Funny thing is that I'll be using the same graphics and animation from a similar tutorial I did some years ago. But back then I did it using a javascript library which involved keeping values in variables, some mathematics, recursive functions and a lot of logic.

Today, I'm achieving the same results without any of that. Plain simple CSS properties. And I'm telling you, the result is even more fluid than my old overly complex javascript. I love the way CSS is heading and I'm excited about a lot of what CSS3 already has to offer.

Here we go. Let's start with a boring, non-moving, sky.

#scene {
    width: 600px;
    height: 250px;
    background: 
        url(cloud-1.png) repeat-x,
        url(cloud-2.png) repeat-x,
        url(cloud-bg.jpg);
}
 

I like cartoony clouds.

I've layered everything on one single background, a new feature of CSS3. It's pretty simple, keeping the same good old syntax you're used to but separate each background layers with a comma starting from front to back layers.

Why is everything on different layers? Because we want things to move in different ways!

Then let's get things moving. YES, we're still doing CSS3. No script, no Flash involved here.

@-webkit-keyframes scene2 {
    0% { background-position: 0px 0, 0px 0, 0 0; }
    100% { background-position: 1200px 0, 600px 0, 0 0; }
}
@-moz-keyframes scene2 {
    0% { background-position: 0px 0, 0px 0, 0 0; }
    100% { background-position: 1200px 0, 600px 0, 0 0; }
}
@-o-keyframes scene2 {
    0% { background-position: 0px 0, 0px 0, 0 0; }
    100% { background-position: 1200px 0, 600px 0, 0 0; }
}
@-ms-keyframes scene2 {
    0% { background-position: 0px 0, 0px 0, 0 0; }
    100% { background-position: 1200px 0, 600px 0, 0 0; }
}
@keyframes scene2 {
    0% { background-position: 0px 0, 0px 0, 0 0; }
    100% { background-position: 1200px 0, 600px 0, 0 0; }
}

.scene2 {
    width: 600px;
    height: 250px;
    background: 
        url(cloud-1.png) repeat-x,
        url(cloud-2.png) repeat-x,
        url(cloud-bg.jpg);
    -webkit-animation: scene2 15s linear infinite ;
    -moz-animation: scene2 15s linear infinite ;
    -o-animation: scene2 15s linear infinite ;
    -ms-animation: scene2 15s linear infinite ;
    animation: scene2 15s linear infinite ;
}
 

WOAH!!! That's a lot of Chinese code, but it looks awesome! It's not half as bad as it looks. There's just a lot of repetition for all the vendor prefixes.

First, we define our @keyframes. Very complex stuff in a few words, using percentages you simply tell CSS what are the attributes value for each key frame (for each percentage value). In our case, we start with the background-position in its initial position and in the last frame it's moved on the x-axis. 1200px and 600px are used so the animation is smooth when it loops. As you can see the front clouds are moving twice as fast as the background ones because we're moving them by twice the amount of pixels to the right.

Secondly, we add the animation property to our scene styles using the alias we gave to our @keyframes, the time the animation will take to reach the end (the 100% key frame), the easing (we use linear so the animation stays constant) and the last property is how many time the animation should play (we picked infinite, since clouds never stops!).

Next, I'll be adding the dancing sun to our sky. Hold on your breath because this is going to be painful.

@-webkit-keyframes clouds {
    0% { background-position: 0px 0, 0px 10px; }
    50% { background-position: 600px 30px, 300px 0; }
    100% { background-position: 1200px 0, 600px 10px; }
}
@-moz-keyframes clouds {
    0% { background-position: 0px 0, 0px 10px; }
    50% { background-position: 600px 30px, 300px 0; }
    100% { background-position: 1200px 0, 600px 10px; }
}
@-o-keyframes clouds {
    0% { background-position: 0px 0, 0px 10px; }
    50% { background-position: 600px 30px, 300px 0; }
    100% { background-position: 1200px 0, 600px 10px; }
}
@-ms-keyframes clouds {
    0% { background-position: 0px 0, 0px 10px; }
    50% { background-position: 600px 30px, 300px 0; }
    100% { background-position: 1200px 0, 600px 10px; }
}
@keyframes clouds {
    0% { background-position: 0px 0, 0px 10px; }
    50% { background-position: 600px 30px, 300px 0; }
    100% { background-position: 1200px 0, 600px 10px; }
}

@-webkit-keyframes sun {
    0% { -webkit-transform: rotate(0deg); transform:rotate(0deg); }
    100% { -webkit-transform: rotate(150deg); transform:rotate(150deg); }
}
@-moz-keyframes sun {
    0% { -moz-transform: rotate(0deg); transform:rotate(0deg); }
    100% { -moz-transform: rotate(150deg); transform:rotate(150deg); }
}
@-o-keyframes sun {
    0% { -o-transform: rotate(0deg); transform:rotate(0deg); }
    100% { -o-transform: rotate(150deg); transform:rotate(150deg); }
}
@-ms-keyframes sun {
    0% { -ms-transform: rotate(0deg); transform:rotate(0deg); }
    100% { -ms-transform: rotate(150deg); transform:rotate(150deg); }
}
@keyframes sun {
    0% { transform:rotate(0deg); }
    100% { transform:rotate(150deg); }
}

.sky {
    position: relative;
    background: url(cloud-bg.jpg);
    width: 600px;
    height: 250px;
    border-radius: 20px;
}
.clouds {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
    width: 600px;
    height: 250px;
    background: 
        url(cloud-1.png) repeat-x,
        url(cloud-2.png) repeat-x;
    -webkit-animation: clouds 15s linear infinite ;
    -o-animation: clouds 15s linear infinite ;
    -moz-animation: clouds 15s linear infinite ;
    -ms-animation: clouds 15s linear infinite ;
    animation: clouds 15s linear infinite ;
    border-radius: 20px;
}
.sun {
    position: absolute;
    top: 15px;
    left: 100px;
    -webkit-animation: sun 4s ease-in-out infinite alternate;
    -moz-animation: sun 4s ease-in-out infinite alternate;
    -o-animation: sun 4s ease-in-out infinite alternate;
    -ms-animation: sun 4s ease-in-out infinite alternate;
    animation: sun 4s ease-in-out infinite alternate;
    z-index: 1;
}
 

Now that's a lot of CSS! It's all the same concept as I've explained in the previous step and again many duplications for vendor prefixes.

I added a @keyframes to rotate the sun. To position the sun behind the clouds I separated the clouds from the sky and added them on their own layer which I positioned on top of the sun using the z-index. I could not add the sun as a background layer because I want to rotate it and at this time you cannot rotate a background in CSS.

Also, did you notice how I vary the y-axis value to make the clouds go up and down making them look alive? This is to show you an example with more than just the 0% and 100% key frames.

This may seem like a lot of complex CSS simply to move clouds around but the goal is to show the potential of CSS3. And as I've explained in my introduction, I did the same in javascript in the past and believe me this is much simpler.

In this example I use a sky with clouds but you can use anything fitting to your website. A moving background behind a moving car for a car rental business would be awesome.

If you want more you can have a look at my previous CSS3 Trick post.

Try it on your own, play with my code, be creative and share your findings with everyone.

P.S.: Browser support: Firefox 5+, Safari 4+, Chrome 4+, IE 10+, Opera 12+

P.S.S.: Nothing bad can really happen if the browser does not support. It'll show a still background and they won't ever know they're missing awesome animations. Shame.

Comments