loading...
support-sprite-fallback

CSS Sprite Animation with WordPress Integration

by Chris McCrow

With web technologies advancing fast websites are getting more and more interactive. With the downfall of flash other technologies have had to evolve to offer the same levels of user experience (without the crippling bugs).

For animation we actually now have a range of different options. There’s css3 animation and transitions, video that embeds straight in the page, gifs, and javascript options too (including the use of the canvas element). Today however we’re covering sprite animation.

A sprite is an image that can be compiled into a long sheet of images called a spritesheet. Here is an example of the mechanical arm from the homepage (Click for full size):

support-sprite

Using animated sprites in web is a form of css animation, but rather than animating the element itself, you use it to show different frames of the animation at a speed you want.

Using CSS to Make the Animated Sprite

First off, we want to make it so that our sprite only shows one frame at a time. For this we’ll make it a background-image of an element, and set the element’s width and height to the size of one frame:

<div class="my-sprite"></div>
<style>
.my-sprite{
	width: 300px;
	height: 200px;
	background-image:url(path/to/my/image);
}
</stlye>

That’s great, but a bit boring. Lets get it moving. I’m going to add the animation property to my sprite. This includes the animation name (my-sprite-animation), the time it takes to do the animation (1.2s) and the times I want it to repeat (infinite).

I’m also adding the details of my animation here. I want my animation to go through all the frames, so I want to move the background upwards from where it starts, to where the final frame will be visible in the element. The ‘background-position’ property here helps out, by defining the backgrounds position in relation to the element. You can specify an x and y position, but as my spritesheet is vertical I’ll be moving it vertically. The y position I want to end the animation loop on is the height of one frame, times one less than the total amount of frames (otherwise it’ll loop through to the first frame again). Or, if it’s easier, the height of your spritesheet minus 1 frame.

<div class="my-sprite"></div>
<style>
.my-sprite{
	width: 300px;
	height: 200px;
	background-image:url(path/to/my/image);
	animation: my-sprite-animation 1.2s infinite;
}
@keyframes my-sprite-animation{
	0%{background-position: 0px 0px;}
	100%{background-position: 0px -5800px;}
}
</stlye>

We’re nearly there, but there’s one last thing to add. Rather than scrolling through the frames, we obviously want it to pause and show each individually. For this there is the steps(x) animation timing function. We want it to step one less times than we have frames, and you can add this in either under the css property ‘animation-timing-function’, or put it in just before the repeat amount (infinite):

<div class="my-sprite"></div>
<style>
.my-sprite{
	width: 300px;
	height: 200px;
	background-image:url(path/to/my/image);
	animation: my-sprite-animation 1.2s steps(29) infinite;
}
@keyframes my-sprite-animation{
	0%{background-position: 0px 0px;}
	100%{background-position: 0px -5800px;}
}
</stlye>

Coolio, so that’s done – but I don’t really want to have to type that all out every time I want to add an animated sprite. The solution?

Making All That into a Shortcode

I did say ‘with WordPress Integration’ after all.

Ok, so if you’ve into WordPress development and have added a shortcode before this shouldn’t be too hard to follow, but if anything’s unclear just whack a comment below and I’ll add in an update. I am going to assume you’ve used a shortcode before.

When adding a sprite here’s a few things I want to specify:

  • The Spritesheet
  • A Fallback, possibly for smaller devices
  • The size of the monitor my fallback stops being a fallback and becomes a sprite.
  • The dimensions of my sprite.
  • The speed of my sprite.

The shortcode I want to create should look like this in the editor:

[add_Sprite spritesheet="path/to/spritesheet" fallback="path/to/fallback" min_width="Number" width="Number" height="Number" speed="Number"]

Here’s the structure of my shortcode function:

function cc_add_sprite($atts){
  $a = shortcode_atts( array(
    'spritesheet' => '',
    'fallback' => '',
    'min_width' => '100',
    'width' => '150',
    'height' => '150',
    'speed' => '0.05'
  ), $atts );
  
  $returnString = '';
  return $returnString;
}
add_shortcode('add_Sprite', 'cc_add_sprite');

$returnString is the string I’m going to build on throughout the function (with ‘.=’), and then return at the end. Currently it returns nothing. There are two more things I’ll need to know for my code; the amount of frames and a unique class to link my sprite to it’s css. Didn’t want to have to specify these, as we can make our shortcode work out the frames and use the spritesheet url as our class (with slashes etc. removed):

function cc_add_sprite($atts){
  $a = shortcode_atts( array(
    'spritesheet' => '',
    'fallback' => '',
    'min_width' => '100',
    'width' => '150',
    'height' => '150',
    'speed' => '0.05'
  ), $atts );

  $class = preg_replace('/[^\p{L}\p{N}\s]/u','',$a['spritesheet']); // Here's my unique class

  $spriteSize = getimagesize($a['spritesheet']); // 'getimagesize' is a php function that gets the dimensions of image files
  $frames = $spriteSize[1]/$a['height'] -1; // Here's my amount of frames

  $returnString = '';
  return $returnString;
}
add_shortcode('add_Sprite', 'cc_add_sprite');

Adding my sprite without any css is easy, it’s just an element with my class.

  $returnString .= '<div class="' . $class . '"></div>';

And adding my simple base css.

  $returnString .= '<style>';
  $returnString .= "  .$class {";
  $returnString .= "    width: ${a['width']}px;";
  $returnString .= "    height: ${a['height']}px;";
  $returnString .= "    background-image: url(${a['fallback']});";
  $returnString .= '  }';
  $returnString .= '</style>';

My sprite css I want in a media query, so it only kicks in at a certain width.

  $returnString .= '<style>';
  $returnString .= "  .$class {";
  $returnString .= "    width: ${a['width']}px;";
  $returnString .= "    height: ${a['height']}px;";
  $returnString .= "    background-image: url(${a['fallback']});";
  $returnString .= '  }';
  $returnString .= "  @media(min-width:${a['min_width']}px){";
  $returnString .= "    .$class {";
  $returnString .= "      background-image: url(${a['spritesheet']});";
  $returnString .= "      animation: ${class}_sprite " . ($frames * $a['speed']) . "s steps(${frames}) infinite normal forwards;";
  $returnString .= '    }';
  $returnString .= '  }';
  $returnString .= '</style>';

Lastly, my animation.

  $returnString .= '<style>';
  $returnString .= "  .$class {";
  $returnString .= "    width: ${a['width']}px;";
  $returnString .= "    height: ${a['height']}px;";
  $returnString .= "    background-image: url(${a['fallback']});";
  $returnString .= '  }';
  $returnString .= "  @media(min-width:${a['min_width']}px){";
  $returnString .= "    .$class {";
  $returnString .= "      background-image: url(${a['spritesheet']});";
  $returnString .= "      animation: ${class}_sprite " . ($frames * $a['speed']) . "s steps(${frames}) infinite normal forwards;";
  $returnString .= '    }';
  $returnString .= '  }';
  $returnString .= "  @keyframes ${class}_sprite{";
  $returnString .= '    0%{background-position: 0px 0px;}';
  $returnString .= "    100%{background-position: 0px -" . ($spriteSize[1] - $a['height']) . "px;}";
  $returnString .= '  }';
  $returnString .= '</style>';

A final look at all the shortcode together.

function cc_add_sprite($atts){
  $a = shortcode_atts( array(
    'spritesheet' => '',
    'fallback' => '',
    'min_width' => '100',
    'width' => '150',
    'height' => '150',
    'speed' => '0.05'
  ), $atts );

  $class = preg_replace('/[^\p{L}\p{N}\s]/u','',$a['spritesheet']); // Here's my unique class

  $spriteSize = getimagesize($a['spritesheet']); // 'getimagesize' is a php function that gets the dimensions of image files
  $frames = $spriteSize[1]/$a['height'] -1; // Here's my amount of frames

  $returnString = '';

  $returnString .= '<div class="' . $class . '"></div>';

  $returnString .= '<style>';
  $returnString .= "  .$class {";
  $returnString .= "    width: ${a['width']}px;";
  $returnString .= "    height: ${a['height']}px;";
  $returnString .= "    background-image: url(${a['fallback']});";
  $returnString .= '  }';
  $returnString .= "  @media(min-width:${a['min_width']}px){";
  $returnString .= "    .$class {";
  $returnString .= "      background-image: url(${a['spritesheet']});";
  $returnString .= "      animation: ${class}_sprite " . ($frames * $a['speed']) . "s steps(${frames}) infinite normal forwards;";
  $returnString .= '    }';
  $returnString .= '  }';
  $returnString .= "  @keyframes ${class}_sprite{";
  $returnString .= '    0%{background-position: 0px 0px;}';
  $returnString .= "    100%{background-position: 0px -" . ($spriteSize[1] - $a['height']) . "px;}";
  $returnString .= '  }';
  $returnString .= '</style>';

  return $returnString;
}
add_shortcode('add_Sprite', 'cc_add_sprite');

Congrats, this actually kind of works now. You’ll see some of the sprites on the homepage are slightly more advanced, if there are any requests I can cover this in another post.

The code presented here is for learning purposes and I can’t be responsible for what you do with it, but if you want it, take it. Try progressing on it by adding a loop for css prefixes (recommended), or add in other features like moving the sprite on hover, or scaling.

Useful links:


2 comments on “CSS Sprite Animation with WordPress Integration

Leave a Reply

Your email address will not be published. Required fields are marked *