CSS Animated pixel art (game sprites)

by Wayne Smith

Retro game design uses a series of images or sprites to create an animated charactor. Web pages or HTML5 games can use the same technique. The advantage of using CSS to display the sprites is CSS is non-blocking for user interactions, and can be controled via javascript. This type of animation in the browser is not resource intensive and the browser can take advantage of any available graphics processor.

To animate any sprite which contains all of the images the only thing that needs to be done is mask off the portion of the image which is not used; And, move the image to each frame in sequence. Moving the wrapper divide moves the animated image across the screen.

Walking Cat

Running Cat

The sprite for the smaller running, jumping cat has an arrangement of 5 and 3 images in the sprite, the major difference is the @keyframes running-cat for this sprite. His short legs makes him move slower.


<div class="pixel-art">
<div id="cat-walking">
<img class="character-spritesheet" src="imgbin_cat-walk-cycle-animated-film-drawing-sprite-png.png" />
</div>
</div>


<div class="pixel-art">
<div id="cat-small" >
<img src="cat-221-154-8.png">
</div>
</div>


<style>
.pixel-art {
width:auto;
}


#cat-walking {
width: 400px;
height: 200px;
overflow: hidden;
position: relative;
animation: cat-walking-move 4s linear infinite;
}


@keyframes cat-walking-move {
0% {
opacity: 0;
left:70%;
}
8% {
opacity: 1;
}
95% {
opacity: 1;
}
100% {
opacity: 0;
left:0%;
}
}


#cat-walking>img {
animation: cat-walking 1.2s steps(12) infinite;
}


@keyframes cat-walking {
from {
transform: translate(0px,0)
}
to {
transform: translate(0px,-100%)
}
}


#cat-small {
width: 128px;
height: 90px;
overflow:hidden;
position:relative;
animation: cat-movement 8s linear infinite;
}


@keyframes cat-movement {
0% {
opacity: 0;
right:0px;
}
5% {
opacity: 1;
}
95% {
opacity: 1;
}
100% {
opacity: 0;
right:calc(100% - 400px);
}


#cat-small>img {
width:640px;
position:absolute;
animation: running-cat .8s infinite;
animation-timing-function: steps(1, end);
}


@keyframes running-cat {
0% {
transform: translate(0px,0);
}
12.5% {
transform: translate(-128px,0);
}
25% {
transform: translate(-256px,0);
}
37.5% {
transform: translate(-384px,0);
}
50% {
transform: translate(-512px,0);
}
62.5% {
transform: translate(0px,-90px);
}
75% {
transform: translate(-128px,-90px);
}
87.5% {
transform: translate(-256px,-90px);
}
100% {
transform: translate(0px,0);
}
}
</style>