Creating animation with CSS3, an alternative to Flash (Part 1)

Last month the Interactive Content Team developed the LHSA – HIV/AIDS website and I thought it might be nice to show you how the simple animation of the bus on the home page was created.

Firstly, as the title of this blog post would suggest, it was not created using Adobe Flash (for those of you unfamiliar with this technology read the “brief history of flash” below). This simple animation was created using CSS3, a little HTML code and some jQuery.

It was adapted from an original idea I had to test the capabilities of CSS3 animation, and to see if it could measure up to the capabilities of Flash. I found this really helpful tutorial online by Rachel Nabors (Flashless Animation) and basically took it from there.

This was my starting exercise below:

You can see the idea is pretty simple; I have a bus in the centre of the screen, which gives the impression that it’s moving along the street. However, the bus never moves from its position on the screen. The bus is in fact stationary, only the wheels are moving. The items that are moving are the street scene and background layers. By moving these in the opposite direction to the bus gives the impression that the bus is moving along the street.

I like a bit of variety and as one who is familiar with the ever changeable UK weather, it seemed apt to extend the capabilities further by adding buttons to change the weather conditions and times of day.

I also like to cut corners, so I downloaded this PrefixFree JavaScript file from GitHub and added it to the <head> of my HTML document to save writing CSS prefixes for every browser.

Ok, so how did I do this?

To create this animation I’ve used a combination of;

  1. HTML code
  2. CSS3 animation
  3. Spritesheet for the bus
  4. JavaScript/jQuery code to create the weather conditions and change backgrounds

In this blog post I’ll look at sections 1-3 above and explain how each was achieved. Part 2 of this blog post will deal with the JavaScript/jQuery implementation.

Back to top ^


1. HTML code

First of all, let’s look at the HTML code, and there is not much to it.

<div id="weather"></div>

<div class="foreground" id="fore">
  <ul class="busstops">
    <li id="stop_1">Sunny</li>
    <li id="stop_2">Rainy</li>
    <li id="stop_3">Sunset</li>
    <li id="stop_4">Night</li>
    <li id="stop_5">Snowy</li>
  </ul>
  <button id="buttonStop">Stop the bus</button>
</div>

<div class="midground" id="mid">
  <div class="bus"></div>
</div>

<div class="background" id="back"></div>

You can see that it’s pretty simple – I’ve basically created 4 layers, entitled;

  • Weather – this layer is where the jQuery weather conditions are loaded in.
  • Foreground – this layer contains a UL for the weather buttons as well as a button to “Stop the bus”, which stops the animation. (It is always good practise to provide web users with the option to stop and start animations).
  • Midground – this layer contains the bus and street scene
  • Background – this layer contains the background scenery

These layers are styled and arranged using CSS and z-index layers, which I will discuss further in the next section.

You can see there are no images included in the HTML code, these are all set as background images in the CSS.

Back to top ^


2. CSS3 animation

OK, so now we know what the HTML looks like, and it’s not that scary, let’s have a look at the CSS code. The basic premise is that I have created a scene by layering divs (blocks of content) using the z-index property. (If you are not familiar with the z-index, z-indexes allow you to set the stacking order of html elements. For more information see: W3Schools: z-index).

Lets start with the weather layer.

Weather

This layer is the container for the weather conditions, which are only applied when you select the “Rainy” or “Snowy” buttons at the top of the screen. This layer is positioned at z-index:4 which is the highest layer so this is always on top.

#weather {
  z-index: 4;
}

Foreground

This layer is the container for the buttons and is positioned at z-index:4. This layer is static.

.foreground {
  z-index: 4;
  margin:0 auto;
}

Midground

This layer is positioned at z-index:3 so it appears under both the foreground and weather layers. Midground div layer contains the bus and street scene animation. Here’s the CSS for the street scene animation:

 

.midground {
  animation: parallax_mg linear 20s infinite;
  background: url(edinburgh_ground_normal.png) 0 100% repeat-x;
  z-index: 3;
}
@keyframes parallax_mg {
  0% { background-position: 3000px 100%;}
  100% {background-position: 0 100%; }
}

 

I’m sure most of this CSS looks pretty familiar to those of you who use it. I’ve added a background image (shown below) and set it to repeat it horizontally (repeat-x). The background image is 3000px wide:

edinburgh_ground_normal

It’s the animation: parallax_mg linear 20s infinite line that’s doing the work here, so let’s break it down:

  1. Animation’ is the CSS property, in the same way you would use color.
  2. parallax_mg’ is the animation name, I’ve written this shorthand but it can also be written as animation-name. This name can be anything you want.
  3. linear’ is the timing function of the animation. I’ve used ‘linear’ which means my animation moves with the same speed from start to end. Again, I’ve used shorthand, but written in full it’s animation-timing-function.
  4. 20s’ is the duration of the animation, in my case, I’ve specified it should take 20 seconds to run from start to finish. (animation-duration)
  5. infinite’ is the amount of times the animation should play (animation-iteraction-count), I’ve selected ‘infinite’ to play as a loop, but you can also specify a number if you only want the animation to run a few times.
  6. @keyframes parallax_mg – specifies the animation keyframes. I’m saying move the horizontal or x position of the background image from 3000px (which is the width of the image) to 0px. In other words, from right to left.

(More information on the animation property can be found at W3Schools CSS3 Animations ).

Ok, so if you’ve got this, then the same theory is applied to the background layer, the only difference is that I have used 3 background images rather than 1.

Background

.background {
  background-image:
    url(trees_layer.png),
    url(green_background_2.png),
    url(edinburgh_skyline_1.png);
  background-repeat: repeat-x;
  background-position: 0 100%;
  z-index: 2;
  animation: parallax_bg linear 40s infinite;
  animation-play-state: running;
}

@keyframes parallax_bg {
  0% { background-position: 1800px 100%, 1600px 100%, 1200px 100%;}
  100% { background-position: 0 100%, 0 100%, 0 100%;}
}

I’ve set the trees layer as the top background image (1800px wide)
trees_layer

Then the hill… (1600px wide)
green_background_2
Followed by the Edinburgh skyline image (1200px wide)
edinburgh_skyline_1
You will notice that the background images are not all the same width, this is deliberate; the wider images have more of a distance to move in the animation, so they appear to animate faster. The smaller image of the skyline, which is the furthest away, will move more slowly. This technique is know as parallax scrolling: the background elements move more slowly than the foreground elements creating an illusion of depth. Father Ted viewers may remember him trying to explain a similar concept to Dougal.

You may also notice a new property: animation-play-state: running;

This is where you can specify if the animation is automatically ‘running‘, or ‘paused’ when the page loads. I have toggled this property with JavaScript in section 4.

The HTML layer

Behind all the images I have a static gradient background for the entire page. I have done this by adding a CSS gradient background to the HTML element.

html {
  overflow:hidden;
  height: 100% !important;
  background: rgba(0,176,245,1);
  background: -moz-linear-gradient(top, rgba(0,176,245,1) 0%, rgba(255,255,255,1) 100%);
  background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(0,176,245,1)), color-stop(100%, rgba(255,255,255,1)));
  background: -webkit-linear-gradient(top, rgba(0,176,245,1) 0%, rgba(255,255,255,1) 100%);
  background: -o-linear-gradient(top, rgba(0,176,245,1) 0%, rgba(255,255,255,1) 100%);
  background: -ms-linear-gradient(top, rgba(0,176,245,1) 0%, rgba(255,255,255,1) 100%);
  background: linear-gradient(to bottom, rgba(0,176,245,1) 0%, rgba(255,255,255,1) 100%);
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00b0f5', endColorstr='#ffffff', GradientType=0 );
}

Ok, I hope that makes sense, let’s now look at the bus.

Back to top ^


3. The bus spritesheet

I decided to try out creating a spritesheet within Adobe Flash for the bus. (For more information see this nice online video for an explanation of spritesheets). To do this I created a bus symbol in Flash and then animated the wheels using clockwise motion tweens on a timeline consisting of 16 frames.

I then selected the symbol from the Flash symbol library, (right-clicked) and selected “Generate Sprite Sheet”. I did have to fiddle around with the sprite sheet output options, but by selecting “Custom” for the image dimensions and then setting the output width to match the symbol width and the output height to 16 x the symbol height (= frame number x symbol height) worked for me. Flash provides you with a preview screen and if configured correctly you should see images of your symbol tiled vertically, 1 for each frame used. You can see a smaller version of my bus spritesheet below.
Bus spritesheet
Once the bus spritesheet was created I then used the following CSS to ‘play’ through the spritesheet.

.bus {
  animation: bus-cycle 1s steps(16) infinite;
  animation-play-state: running;
  background: url(animation_spritesheet_ltor.png) 0 0 no-repeat;
  height: 216px;
  width: 384px;
  position: absolute;
  bottom: 60px;
  left: 50%;
  margin-left: -200px;
  transform: translateZ(0); /* offers a bit of a performance boost by pushing some of this processing to the GPU in Safari*/
}

@keyframes bus-cycle {
  0% {background-position: 0 0; }
  100% {background-position: 0 -3472px; } /* Must be full height of sprite or skipping will happen.*/
}

The difference here is that I’ve used the animation-timing-property property ‘steps’ to cycle through the spritesheet in 16 steps from the top of the image to the bottom. Each step lasting 1 second each, the number of steps equalling the number of images in the spritesheet:

animation: bus-cycle 1s steps(16) infinite;

The width and height properties are set to exactly the same width and height of 1 bus in the spritesheet. I did have to tinker with the height settings to make sure this matched exactly 1/16 of the spritesheet. Being out by a few pixels resulted in a rather bumpy rendering of the bus rather than a smooth transition.

The background-position is set to move from 0px to -3472px, this is the full height of the spritesheet image.

Summary

So, if you’ve got this far and you’re still reading, well done, and thanks for staying with it. There are plenty more things I could do with CSS3 animation, and this blog post is only a very brief overview, but hopefully this will have given you some ideas to get started with.

In my next blog post I’ll look at Section 4: JavaScript/jQuery code for the weather generation.

Back to top ^


Useful links and references

Images from:

Brief history of Flash

Brief history of Flash


When I first started working in the web industry Macromedia Flash as it was known then, was considered one of the coolest things around. Macromedia Flash was a program where you could create rich interactive media content with shiny scalable vector graphics that looked the same in all browsers, (providing you had the plugin installed). This might not sound amazing, but this was in the late 1990s and the vastly different webpage rendering of Netscape Communicator and Internet Explorer 5, meant trying to get your website to look the same in both these browsers was a mammoth task; CSS was not supported well, and layout was controlled using tables and the infamous transparent spacer.gif. Flash was great; a flash object looked the same in all browsers, it could scale to fit the screen and the file size was tiny, handy when you were using that dial-up-modem to get online. All you had to do was download the flash plugin to play content in your browser.

Flash was so popular that it soon became the fashion for websites to have a full screen launch page, yep all 480 x 640 pixels of it. Who remembers visiting websites and being asked to choose between the “HTML” or “Flash” version, like who would want to visit the boring HTML version right, when you could experience the fun flash version with animations and games?

However, as web technologies developed Flash found it’s place as the tool of choice for banner ads, games, simulations and e-learning objects. All was good for the next decade or so, and then in 2007 Apple invented the iPhone, the iPad followed in 2010 and mobile and tablet browsing became THE thing. Apple would not allow Flash player on the iPhone and iPad, it made the devices unstable and took up too much processing memory. Due to the rising popularity of mobile and tablet browsing alternatives to Flash had to be sought. This leads me to the start of HTML5 as an alternative to Flash.

For more information please read: Wikipedia: Apple and Adobe Flash controversy

Back to top ^