A quick introduction to SVG animation
Tags: css, svg, animation
Published: 2019-08-12 18:03:14

In the past few days I worked a lot with SVGs. For years I used Illustrator for graphic purposes, but I never touched the source code of what I did, even less animated.

To better understand this marvelous technology, I decided to go deeper in the topic and the mess of paths and coordinates has become much more clear.

In this my first post on DEV.to I want to share with you my knowledge about SVGs, so you can spicing up your next project.

## Small recap about SVGs

If you don't know what SVGs are, don't be afraid, read this easy explanation.

SVG stand for Scalable Vector Graphics, it's a technology able to visualize a vector graphic objects and, therefore, to manage scalable images dimensionally.
 
SVG its standardized by W3C, you can read the documentation [here](https://www.w3.org/TR/SVG11/).

## Here we go

Now that the definition of SVG is clear for everybody, let's deep dive into.

Let's start talking about the SVG itself, the object that we want to animate. I think that no one create with code from scratch an SVG, for that you can use Adobe Illustrator or Inkscape (there are a plenty number of software that permit to create SVGs).

For this introduction I created on Illustrator the classic batman logo
![Classic Batman Logo](https://i.imgur.com/MVJEKka.jpg)

And that's the code

```xml
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 595.28 841.89" style="enable-background:new 0 0 595.28 841.89;" xml:space="preserve">
<style type="text/css">
	.st0{fill:none;stroke:#010101;stroke-miterlimit:10;}
</style>
<path class="st0" d="M340.44,418.45c-2.83,4.36-7.29,8.3-13.24,11.72c-2.98,1.72-6.2,3.22-9.8,4.59c0.98-1.21,1.97-2.47,2.86-3.83
	c1.06-1.61,2.45-4.05,2.33-6.68c-0.11-2.32-1.31-4.54-3.08-5.66c-1.95-1.24-4.85-1.32-7.06-0.2c-2.55,1.3-3.85,4.14-5.06,6.94
	c-0.49-0.64-0.99-1.3-1.51-1.94c-1.05-1.3-2.24-2.6-3.76-3.33c-1.84-0.87-4.23-0.94-6.09-0.16c-2.28,0.96-3.8,3.16-4.98,5.19
	c-1.13,1.93-2.12,3.98-3.2,6.66c-0.96,2.35-1.83,4.8-2.67,7.18c-0.85-2.38-1.73-4.83-2.67-7.18c-1.09-2.67-2.07-4.73-3.2-6.66
	c-1.19-2.03-2.7-4.23-4.98-5.19c-0.87-0.37-1.86-0.55-2.85-0.55c-1.13,0-2.26,0.24-3.24,0.7c-1.52,0.73-2.7,2.03-3.76,3.33
	c-0.52,0.64-1.02,1.3-1.51,1.94c-1.21-2.79-2.5-5.65-5.06-6.94c-2.21-1.12-5.11-1.04-7.06,0.2c-1.77,1.12-2.97,3.34-3.08,5.66
	c-0.12,2.62,1.27,5.06,2.33,6.68c0.89,1.36,1.89,2.62,2.86,3.83c-3.61-1.37-6.82-2.87-9.8-4.59c-5.95-3.43-10.41-7.37-13.24-11.72
	c-3.27-5-4.36-10.5-3.1-15.47c0.73-2.84,2.31-5.89,4.6-8.8c2.94-3.75,6.82-6.99,11.87-9.89c3.3-1.9,6.9-3.56,10.68-4.91
	c2.55-0.91,5.3-1.73,8.39-2.5c-1.2,1.44-2.02,2.49-2.78,3.64c-1.5,2.28-2.35,4.34-2.59,6.31c-0.26,2.08,0.16,4.17,1.19,5.89
	c0.94,1.59,2.42,2.94,4.16,3.81c1.93,0.96,4.09,1.28,6.09,0.9c1.2-0.23,2.34-0.71,3.27-1.4c2-1.48,3.36-4.05,4.16-7.88
	c0.44-2.1,0.62-4.16,0.79-6.17l0.04-0.46c0.21-2.39,0.45-4.85,0.69-7.23l3.88,5.75h7.91l3.88-5.75c0.24,2.38,0.48,4.84,0.69,7.23
	l0.04,0.46c0.17,2.01,0.36,4.07,0.79,6.17c0.8,3.82,2.16,6.4,4.16,7.88c0.93,0.69,2.06,1.18,3.27,1.4c2,0.38,4.16,0.05,6.09-0.9
	c1.75-0.87,3.22-2.23,4.16-3.81c1.02-1.73,1.43-3.81,1.19-5.89c-0.24-1.97-1.09-4.03-2.59-6.31c-0.75-1.14-1.57-2.19-2.78-3.64
	c3.1,0.77,5.85,1.59,8.39,2.5c3.79,1.35,7.38,3.01,10.68,4.91c5.05,2.91,8.94,6.15,11.87,9.89c2.28,2.91,3.87,5.95,4.6,8.8
	C344.81,407.95,343.7,413.44,340.44,418.45z"/>
</svg>

```

## Optimize the code

Before proceeding further I use [SVGOMG](https://jakearchibald.github.io/svgomg/) to optimize the code generated from Illustrator. Just paste the code and the tool will do the rest. The default settings are good, but you're free to play with them to obtain an higher o lower optimization.

Mine SVG after the optimization is 88% lighter.

Click the icon to copy the optimized code and paste it in your code editor into a new HTML file.

## Set up the playground

Create a new CSS file and, just for demo purpose, center the SVG in the viewport, how to do it? Well it's pretty simple, the SVG element is a block element so there's no magic here

```css
svg {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}
```

What I want to achieve is to animate the outline, making it look like it's being drawn.

First of all we need to define an initial state and for that we need two properties [`stroke-dasharray`](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray) and [`stroke-dashoffset`](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset). What this two properties does is simple:
 - `stroke-dasharray` define the pattern of dashes and gaps in and outline of a shape.
 - `stroke-dashoffset` define the offset on the rendering of the associated dash array.

Which number do you need to use in this two properties, well, you can guess it, or you can use Javascript to find the right one.

### Let's find the path length
To find out the right path length you can use the code below:

```javascript
let path = document.querySelector('path');
let pathLength = path.getTotalLength();
console.log(pathLength)
```

A more advanced solution can be the one where you modify a CSS variable with Javascript, but it's up to you to understand how :)

The code above will print in the console the path length. That number is the one that we need to give to `stroke-dasharray`, and the same value, but negative, to `stroke-dashoffset`.

## Create the animation

To animate the outline we need to use our old friend, the `keyframes`

```css
path {
  stroke-dashoffset: -1419;
  stroke-dasharray: 1419;
}

@keyframes draw-logo {
  from {
    stroke-dashoffset: -1419;
  }
  to {
    stroke-dashoffset: 0;
  }
}
```

What this code mean? We create an initial breakpoint where the `stroke-dashoffset` is set to the negative value of the path length (in my case -1419, your will be different if you use a different figure) and then we set a final breakpoint where `stroke-dashoffset` is set to 0. In other words we can translate this animation as follows "from hidden to fully drawn".

If you want to invert the line drawing you need to change -1419 to 1419.

## Apply the animation

Now that we've the animation in place we can apply it to the SVG path. For this purpose we need to use the `animation-*` properties.

```css
path {
  stroke-dashoffset: -1419;
  stroke-dasharray: 1419;
  animation-name: draw-logo;
  animation-duration: 2s;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-tiiming-function: ease-in;
  animation-fill-mode: forwards;
}

@keyframes draw-logo {
  from {
    stroke-dashoffset: -1419;
  }
  to {
    stroke-dashoffset: 0;
  }
}
```

Let's analyze what we've written

 - `animation-name`: it's pretty simple is the name of the animation that we created before using the `@keyframes`
 - `animation-duration`: how much time the animation need to complete
 - `animation-iteration-count`: how many times the animation it'll repeated
 - `animation-direction`: where the animation go, the value are `normal`, `reverse`, `alternate` and `alternate-reverse` play with it
 - `animation-timing-function`: how the animation progresses during his cycle
 - `animation-fill-mode`: what styles the animation applies before and after its execution.

You can use the shorthand `animation`, but it's not really understandable like other ones like `font`, `background` and others.

You can check the final result [here](https://codepen.io/manuelvrc/pen/bXyOVy)

## Conclusion

Well done, you've created your first SVG animation with CSS and a little bit of JS.

What do you think? Let me know in the comments :)