How to create a responsive vector animation

by Ian Jackson, UX Developer @ ClearPeople

When it comes to animation, in terms of web development, we have a few different techniques at our fingertips. The way in which an animation is created depends on the intention and style of the desired animation. Perhaps the purpose of it is to showcase an illustrator’s natural drawing style, it could be an animated video game character, or maybe the purpose of it is to be displayed in an HTML email. Depending on the intention, the developer can accomplish the animation a few different ways.

In this case, we will be creating a high quality 2d animation format which must work on all modern devices (mobiles, tablets, desktops), looks nice on both high resolution and low resolution screens and doesn’t require Javascript to work.

Our aim

We are going to animate this vector humming-bird using CSS animations

Bird

CSS animations differ from JS and Flash based animations by allowing the browser to better optimise performance.

The image is an SVG (Scalable Vector Graphic) file. They are a lot smaller in size compared to JPG, PNG, and GIF. They can also be scaled to any size without any loss of image quality.

Preparation

First, we need to visualise the animation. This is going to be a simple movement. The wings are going to flutter, the tail is going to bounce, and the whole body is going to hover up then back down.

The next step is to identify the independent parts. For the bird, we have 4 independent parts: two individual wings, a tail, and the remaining body.

These parts will need to be separated out using a Vector graphics editor such as Adobe Illustrator.

Our original SVG image is 150px by 112px. We need to split this image into 4 body parts and position them below one another.

Bird

Next we are going to create some HTML to represent our bird’s moving parts.

<div class="model">
	<div class="model-bird">
		<div class="wing2"></div>
		<div class="wing1"></div>
		<div class="tail"></div>
		<div class="body"></div>
    </div>
</div>

Of course this means nothing without adding some CSS to our classes.

The first thing we need to do is create a responsive structure with these divs. Ideally we would like the bird to resize easily while maintaining the aspect ratio of the image

Defining an image aspect ratio

This is something which happens naturally when working with an HTML <img> element. The ratio, of width to height, will always remain equal unless otherwise changed. This is not the case when using div elements. This means we need to define the correct ratio using CSS. We know that the size of our bird image is 150px by 112px. From this we can deduce that the ratio of height to width is:

112 = 0.7466666666666667
150

This value is the aspect ratio of our image. To represent this as a percentage, we multiply the value by 100. That gives us 74.666%.

So, if the image is 100% wide, then it is 74.666% high.

In our CSS we can write this as follows:


.model {
	position: relative;
}

.model-bird > div {
	width: 100%;
	padding-bottom: 74.666666%;
}

This will set the correct proportion for each bird component. We use the padding-bottom value here because padding, when expressed as a percentage, is calculated relative to the width of the element. This mimics the native behaviour of the <img> element.

If we inspect the components with Chrome we can see the green padding box is the correct shape to contain our bird image.

Inspector

Now we can apply a background image to each component.

.model-bird > div {
	width: 100%;
	padding-bottom: 74.666666%;
	background-image: url(bird.svg);
	background-repeat: no-repeat;	
	background-size: 100%;
	position: absolute;
	top: 0;
	left: 0;
}

This addition applies the bird image as a background image to each component while positioning each component on top of one another so that they are overlaid.

Inspector

Now we can see the bird’s body which is the top part of the svg image. Next, we need to adjust the vertical position of each part so that they appear in the correct position on the bird. Since each part is equally distant from one another we can figure out the correct position easily.

Let's add the following CSS:

.model-bird .wing2 {
	background-position: 0% 33.3333%;
}
.model-bird .wing1 {
	background-position: 0% 66.6666%;
}
.model-bird .tail {
	background-position: 0% 100%;
}
.model-bird .body {
	background-position: 0% 0%;
}

Since we have 4 equal parts, we can shift the background position of each part by 0%, 33.333%, 66.666% and 100% and it now we see our bird as it should appear.

Inspector

Earlier when we created the HTML structure, we placed the bird parts in the following order:

  1. Wing1
  2. Wing2
  3. Tail
  4. Body

This structure takes into account which layer should appear behind and which layer should appear in front.

If we were to rearrange these parts, we end up with an image which looks like this:

Inspector

Animating

Now that we have created our responsive structure, and positioned our bird’s layers, we can now add the animation. We are going to define an animation keyframe set for each wing flutter, the tail bounce, and the body hover.

CSS keyframes allow authors to control the intermediate steps in a CSS animation sequence by establishing waypoints at particular intervals. They currently require browser vendor prefixes to work properly across browsers. In this example, for simplicity, I will use the standard notation without prefixes.

@keyframes flutter {
	0% {
		transform: rotate(0deg);
	}

	50% {
		transform: rotate(-10deg);
	}

	100% {
		transform: rotate(0deg);
	}
}

@keyframes flutter-reverse {
	0% {
		transform: rotate(0deg);
	}

	50% {
		transform: rotate(10deg);
	}

	100% {
		transform: rotate(0deg);
	}
}

@keyframes hover {
	0% {
		transform: translateY(0px);
	}

	50% {
		transform: translateY(-10px);
	}

	100% {
		transform: translateY(0px);
	}
}

Here we have defined 3 keyframe sets. Flutter, Flutter-reverse and Hover. Now we apply the keyframe animation sets to our bird parts.

To make the animation loop indefinately, the ‘infinite’ keyword is added to the animation

.model-bird {
	animation: hover 2s infinite;
}
.model-bird .wing2 {
	background-position: 0% 33.3333%;
	animation: flutter ease 0.15s infinite;
}
.model-bird .wing1 {
	background-position: 0% 66.6666%;
	animation: flutter-reverse ease 0.15s infinite;
}
.model-bird .tail {
	background-position: 0% 100%;
	animation: flutter 2s infinite;
}

And that’s all there is to it.