Bringing life to a squid: A CSS3 Animation

Using only CSS3 and HTML, we can create dynamic web friendly animations compatible with most modern browsers. May the squid be with you!

Bringing a Squid to Life

squid sprite sheet
Each frame of the squid’s animation has been mapped out on a single image.

CSS3 has introduced some very advanced new features, my favorite in particular being the ability to animate objects. When I heard animations would be possible I felt excited to try this out and explore the possibilities. This ability goes well beyond a simply link hover effect or menu styling. Objects can be fully animated frame by frame, like a flip book or a cartoon, allowing for many new possibilities. In the past flash was the only option for full web animation. However, flash has a lot of drawbacks. Setting up a flash based website could take months. It required both knowledge of basic web coding and flash animation, plus access to rather expensive software to properly lay out timelines. Hiring a company to build a custom flash site would likely to cost you your life savings plus your first born child. As mobile phones became more like small computers flash took a huge nose dive for it’s incompatibility with these devices. It seems the rise of the smart phone may have officially killed off the era of flash based websites. Animation started to become limited only to those who were masters of Javascript and jQuery, which as far as actual frame animations goes, are still limited. Then behold, awesome new features added to CSS3 allowing me to mess around with all sorts of fun animation options! Thus my love of art and code collide.

For my first project in animation I decided to make a swimming squid. Because squids are awesome, no arguing that. My first step for this was to paint my squid and build a sprite sheet. If you’re not familiar with sprite sheets; it involves putting together each frame of an animation in one image, usually saved as a transparent PNG, so the code can call on each frame as needed without having to load separate image files… would kinda bog down the animation speed and quality. Sprite sheets need to be made very precise and measured out evenly so it’s easy to map the location of each frame on the image. When putting together my squid sprite sheet I included two parts of animation; the first being the actual body of the squid and the second being the squid’s fin. When put together it will be a lovely combination of movement that will mimic a swimming squid!

In planning this out I decided to divide everything up into three separate parts: Part one would be squid moving across the screen, part two would be the body of the squid performing a swimming motion, and part 3 would be the movement of the squid’s fins. Accomplishing this means I will need 3 separate div containers.

Squid Diagram
Basic layout of all our Div’s.

Part 1: Move the squid across the screen

<div id="wrapper">
    <div id="container" align="right">
    </div>
</div>

I made a #wrapper div to define the space in which the squid may move and a #container div to hold the squid itself. Here is the beginning of the CSS (please note that for the purposes of showing examples I’m only including “animation”, however it will be required to also include “-webkit-animation” and “-moz-animation” properties for full browser compatibility. Same goes for keyframes)  :

#wrapper {
	width:100%;
	height:350px;
	position:relative;
	margin:auto;
	overflow: hidden;
}
#container {
    position: relative;
    visibility: hidden;

    animation: move 4s infinite;
}

In the CSS for #container I’ve defined the animation properties. In this case the animation will be called “move”. It will progress for 4 seconds and will run “infinite” (over and over again). The visibility is set to hidden so #container will be invisible by default. Next, I define the properties for “move” using keyframes. Keyframes allow me to tell #container how to animate and break up my animation into steps. I’d like to move #container across the screen from the top right to the bottom left of the page. Because my animation is 4 seconds long I’m dividing my animation into quarters (0%, 25%, 50%, 75%, 100%). These percentages are defined to tell the animation what to do and when to do it :

@keyframes move {  
    0%   {right:-20%; top:0; visibility:visible;}
    25%  {right:20%; top:20%; visibility:visible;}
    50%  {right:40%; top:40%; visibility:visible;}
    75%  {right:60%; top:40%; visibility:visible;}
    100% {right:150%; top:0; visibility:visible;}
}

This seems a little confusing but please bare with me… At the beginning of the animation (0%) I’d like #container to be positioned -20% from the right of #wrapper and 0% from the top of #wrapper. The visibility is now set to “visible”. I had everything hidden before so the viewer would not be able to see any part of the animation until it officially started. This can be especially important if you’re setting an animation delay. By the end of the animation (100%) the squid should be located 150% (so it swims out of page view) from the right and back to 0% from the top of #wrapper. #container will now move across the screen!

Part 2: Make the squid swim

This is similar to what we just did in using keyframes to define an animation property. To make our squid swim we need to animate the frames of our sprite sheet. To do this lets first make a squid container:

<div id="wrapper">
	<div id="container" align="right">
        <div id="squid">
        </div>
    </div>
</div>

Now we have #squid div and it’s going to sit inside of our #container div. Doing this it means that as #container moves across the screen #squid and it’s own animations will move with it. Now lets define our animation for #squid:

#squid {
	animation: swim-cycle 1s steps(11) infinite;
	background: url(images/squidsheetcolor.png) 0 0 no-repeat; 
	height: 50px;
	width: 159px;
	position:relative;
	z-index:1;
}

Let’s break this down. #squid has a very specific height and width (50px by 159px) being the size of a single squid frame. We’re going to set #squid’s background to our sprite sheet and tell it to position the background at the top left corner so it shows our first squid on the sheet.
Our animation will be called “swim-cycle”. This animation will start and finish in 1 second. We have 11 frames total on our sprite sheet to complete a swimming animation so we set 11 steps. And finally, we’d like this animation to run “infinite”. On to the keyframes:

@keyframes swim-cycle 
{  
  0% {background-position: 0 0; } 
  100% {background-position: 0 -551px; }
}	

Looks so simple, huh? But… how exactly does that animate the frames? Well, it involves some math. Thankfully not very complicated math. At the beginning of the animation the background position of the sprite sheet will be set to 0 pixels from the left and 0 pixels from the top. We have 11 steps to be completed and each new frame is an additional 50 pixels from the top. Do some math: 50 pixels x 11 frames = 551 pixels total. So by 100% of the animation we want the background position to be 0 pixels from the left and -551 pixels from the top. The code does this math for us automatically since we defined the number of steps based on how many frames we have AND because each frame is the exact same height/width. This is why it’s very important to have a well laid out sprite sheet! If we didn’t, it would be a HUGE pain to tell it where the background position should be for each and every frame! It really saves us lots of trouble.

Part 3: Make the fins flutter

So our little squid now moves from one side of the screen to the other and he moves his arms in a jet propulsion movement making it look like he’s swimming! Squids also have little fluttery fins on the top of their heads. It would look like a rather unnatural squid without them. Animating the fins will be almost the exact same process as animating the arms. Let’s create our fin container! Add a new div inside of #squid and lets call it #fins.

<div id="wrapper">
	<div id="container" align="right">
        <div id="squid">
            <div id="fins">
            </div>
        </div>
    </div>
</div>

And the CSS will look very similar as well:

#fins {
	animation: fin-cycle 1s steps(11) infinite;
	background: url(images/squidsheetcolor.png) 0 0 no-repeat; 
	height: 25px;
	width: 50px;
	position:absolute;
	top:2px;
	left:5px;
}

Here you see we’ve named our animation “fin-cycle” this time. Again, set up almost exactly the same as #squid. We only needed to adjust the width and height of the div to the size of a single fin frame. In addition, we set absolute positioning so it will appear in the proper place on the squids body inside of the #squid div. Keyframes will also look extremely similar:

@keyframes fin-cycle 
{  
  0% {background-position: -159px 0; } 
  100% {background-position: -159px -275px; }
}

The difference here is in the positioning. The fins are located farther along from the left of the sprite sheet, exactly 159 pixels from the left. So at the beginning of our animation the background position will be set to -159 pixels from the left and 0 pixels from the top. Doing some math again, 25px in height x 11 frames = 275 pixels total. So by 100% of the animation being complete we’d like the background position to still be positioned at -159 pixels from the left (no reason this should have changed) and -275 pixels from the top. Super simple!

Sit back and enjoy watching your squid do his thing. Go squid, go!

Conclusion

Using only CSS3 and HTML we’ve created a really impressive animation. Crazy enough, it could also work for mobile if you condition your code correctly. Combining the abilities of CSS3 with that of JavaScript could allow for full cartoon animations, story lines, user interaction, even sound and music.

I’ve included a download link for this animation which will be formatted a little differently than I’ve shown here to allow for multiple swimming squids and some JavaScript animation control.  I’ve also included the original PSD file and PNG of the squid sprite sheet so anyone may color or alter him to your liking.

Leave a Reply