Making Animated Hand-coded SVG Files

Beginners tutorial on how to hand-code, and animate .svg files with CSS.

2318 views
d

By. Jacob

Edited: 2019-10-14 13:10

Animated SVG

Animating SVGs can be done using simple CSS, the same way you would animate HTML elements. I know how to draw using Illustrator and Inkscape, although I am not very good at it. But, I love coding SVGs by hand!

When coding SVGs by hand, there are a few ways to go about animating them. You can either choose to embed the CSS directly in the SVG file itself, or you can link to it from a HTML web page. Embedded styles in a HTML page will also work, but usually you would link to an external StyleSheet, but this depends on what your goals are.

The SVG code itself should be embedded in the HTML for this to work. If you are creating a .svg file, you should instead embed the CSS within the file. This is done using a <style> element within the <svg> element, at the top, before other elements in the svg.

You can start coding your SVG using <rect> and <circle> to create simple shapes, such as rectangles and circles.

These elements are so-called self-closing elements, and since we are coding XML, the closing slash is mandatory. This is unlike the infamous <br> element or <img> in HTML, where the closing slash may be omitted. In fact, I never use closing slashes when coding HTML, so I was initially unsure if they were needed for embedded SVGs. A quick test, and I found out the SVGs would not be displayed properly if omitted.

Below is a .svg I handcoded and animated using CSS. It took me a couple hours without prior knowledge of coding SVGs by hand.

An animated .svg showing a rocket-truck getting ready to fire.

The basics about SVG

Before I show the code for the above SVG, I will just explain some basics to help you optimize your code.

As you may already know, each SVG element has presentational attributes to control the visual appearance. Some of these attributes can also be controlled with CSS, but support is still por for Geometric attributes. For example, both fill and transform (SVG 1.1) can be controlled with CSS, but the geometric attributes, such as x, y, and r (SVG 2) only seem to work in Chrome. The purpose of replacing presentational attributes entirely, is to produce clean, minimized, SVG code to get as small a file size as possible. Often, WYSIWYG tools will add a lot of redundant code, which just increases the file size. This is not a problem when coding by hand.

Note. x and y controls the position of elements, while fill controls what we typically know as the "background-color". r, the radius of circles.

Just as with basic HTML and CSS, we can use classes and IDs in SVGs. This makes it easy to group repetitive styles in classes, and thereby minimize the amount of code required.

While optimizing code may seem daunting to many beginners, it is actually not hard at all, and does not take much time once you have reached a certain level of skill. The point of doing it, is to lower the file size of the finished .svg files, which in turn speeds up loading of web pages.

If you wish to animate the position of elements, the transform:translate(x,y); may be used instead of x and y. As you can see from my SVG, this can be combined with rotate(10deg) as well.

SVG example code

This code is for the SVG included earlier. Note that you might not be able to edit this when opening it in Illustrator or Inkscape, as these programs do not yet seem to support embedded CSS styles properly. You can however still edit it by hand, and use it as an example of how to create your own hand-coded svgs.

I used nothing but rectangles and circles to create this drawing. The g element is used for grouping, and for easier styling with CSS. Enjoy!

<svg viewBox="0 0 400 300" version="1.1"
     xmlns="http://www.w3.org/2000/svg" standalone="yes">
    <style type="text/css">
    #rocket {
        transform-origin: 60% 100%;
        animation: battleFormationRepeat 10s 0s infinite;
    }
    #rocketLifter rect {
        transform-origin: 100% 50%;
        animation: moveUpDown 10s 0s infinite;
        fill:#007b03;
    }
    #rocketTruckBody #mainBody {
        fill:#007e03;
    }
    #rocketTruckBody #mainAss {
        fill: #004b02;
    }
    #rocketTruckBody #mainControl {
        fill: #004b02;
    }
    .window {
        fill: #000;
    }
    #rocket rect {
        fill: #006302;
    }
    #rocket .panel {
        fill:#004e02;
    }
    #rocket .redStripe {
        fill:#ff0000;
    }
    #star rect {
        transform:rotate(0deg) translate(150px,10px);
        stroke-width: 1;
        stroke: #ffff00;
        fill: none;
    }
    #star rect + rect {
        transform:rotate(45deg) translate(200px,-145px);
    }
    .weel circle {
        fill: #010101;
    }
    .weel circle+circle {
        fill: #494949;
    }
    @keyframes battleFormationRepeat {
        0% {
            transform: rotate(0deg);
        }
        50% {
            transform: rotate(13deg);
        }
        100% {
            transform: rotate(0deg);
        }
    }
    @keyframes moveUpDown {
        0% {
            transform:rotate(0deg);
        }
        50% {
            transform:rotate(10deg);
        }
        100% {
            transform:rotate(0deg);
        }
    }
    </style>
    <g id="rocketLifter">
        <rect width="20" height="70" x="100" y="135"/>
    </g>
    <g id="rocket">
        <rect width="100" height="50" x="200" y="115" />
        <rect width="100" height="50" x="110" y="115"/>
        <rect width="140" height="50" x="40" rx="50" y="115"/>
        <rect width="10" height="50" class="redStripe" x="230" y="115"/>
        <rect width="20" height="20" class="panel" x="90" y="115"/>
        <g id="star">
            <rect width="25" height="25" y="115"/>
            <rect width="25" height="25" y="115"/>
        </g>
    </g>
    <g id="rocketTruckBody">
        <rect width="190" height="40" x="70" y="150" rx="5" id="mainBody"/> 
        <rect width="100" height="60" x="230" y="135" rx="20" id="mainAss"/>
        <rect width="55" height="25" x="60" y="145" rx="5" id="mainControl"/>
        <rect width="20" height="20" x="60" y="145" rx="2" class="window"/>
    </g>
    <g class="weel">
        <circle cx="290" cy="190" r="20"/>
        <circle cx="290" cy="190" r="5"/>
    </g>
    <g class="weel">
        <circle cx="110" cy="190" r="20"/>
        <circle cx="110" cy="190" r="5"/>
    </g>
    <g class="weel">
        <circle cx="155" cy="190" r="20"/>
        <circle cx="155" cy="190" r="5"/>
    </g>
    <g class="weel">
        <circle cx="200" cy="190" r="20"/>
        <circle cx="200" cy="190" r="5"/>
    </g>
    <g class="weel">
        <circle cx="245" cy="190" r="20"/>
        <circle cx="245" cy="190" r="5"/>
    </g>
</svg>

Tell us what you think:

  1. How to add hover effects on links using CSS pseudo classes.
  2. How to create basic transition animations on links and other elements with CSS.
  3. In this tutorial you can learn how to create a nice exploding text transition for your website CV, or for use on a credit roll page. The effect is made with pure HTML and CSS, and no JavaScript is required.
  4. Radial Stripes can be quite fancy when used right in web-design. In this tutorial you will learn how to create animated, rotating radial stripes with CSS.

More in: CSS Animation