The Curious Case of the SVG

Scalable Vector Graphics are a unique feature of the web.

David Mold
JavaScript in Plain English

--

If you are a graphic designer or web developer, you already know how useful SVGs can be. They are small, easy to make, and above all they allow you to create images for web pages that look perfect at every possible size. But they can also be styled with css, and offer multiple ways to create and control animation in your page. Here I show you some very simple ideas to get started with editing and animating them.

When I first found out about the SVG format, I was rather confused by the fact that you can show them in two ways in a web page. You can use them like a regular image:

<img src="/img/mylogo.svg">
Medium won’t let you embed an SVG, so but this is what our starter image looks like.

Watch out though: unless you explicitly set the size of the image, you may get some unpredictable results. For example, the browser may just fill the window with an unsized svg.

Or, you can just put the text content of the file straight into the web page, and it will render just the same:

<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<style>
.cls-1{fill:#fff;stroke:#231f20;stroke-miterlimit:10;}
</style>
</defs>
<g>
<rect class="cls-1" x="8.58" y="8.58" width="38" height="38"
transform="translate(-11.42 27.58) rotate(-45)"/>
<rect class="cls-1" x="8.58" y="29.58" width="38" height="38" transform="translate(-26.27 33.73) rotate(-45)"/>
</g>
</svg>

Note that when you embed svg in a page, you don’t need to include xmlns=”http://www.w3.org/2000/svg" in the svg element — but when used in a standalone file, you must. Also, when used as an embedded element, the css can be defined anywhere in the page, whereas, for a standalone svg, the css must be embedded in the document as show above.

Used in this way, the svg becomes temptingly similar to html. For example, you can make this svg into a Vue component — which is a really fun way to experiment with the capabilities of SVG. I have created a simple svg demo Vue app that you can find here on Github. If you are familiar with Vue, it’s important and liberating to realize that an svg can be a standalone Vue component — or even a part of one. Similar techniques can be used with React and most other frameworks.

In Vue, css styles are added separately, so in my demo, I added a separate style section in a single file component, adding these styles:

<style>
.cls-1{
fill:#f00;
stroke:#231f20;
stroke-miterlimit:10;
}
</style>
Red styling added in Vue stylesheet

It may occur to you, looking at the code for the simple graphic above, that you could create the exact same effect in html just using divs and css styling, which in this case is true — but SVGs provide more complex abilities, like drawing curves, that are difficult to attain by html alone. Still, html can also be a great way to create illustrations and animations, especially if you are adept at exploiting borders and other effects.

If you have some experience with css, you may want to try applying styles and transitions to elements in svgs. It’s important to understand that svg styles share some properties with regular html, have a bunch of their own, and will ignore some of the standard css properties you are used to. The MDN developer reference is a great source for understanding the options available for svg elements.

One of the most intriguing things about svgs is that they can contain animated elements. If you pop an animate element inside another element (in our example a rect), it will both define and control animations of that element. For example, with our simple logo we can add this line:


<svg viewBox="0 0 46 80">
<g>
<rect class="cls-1" x="8.58" y="8.58" width="38" height="38" transform="translate(-11.42 27.58) rotate(-45)">
<animate attributeName="rx" values="0;20;0" dur="5s" repeatCount="indefinite" /> </rect>
<rect class="cls-1" x="8.58" y="29.58" width="38" height="38" transform="translate(-26.27 33.73) rotate(-45)"/>
</g>
</svg>
Using the attributeName rx to animate the corner radius of the upper diamond.

and now, magically, our simple logo is animated. You will notice that we are animating the attributeName “rx”. You may not easily guess that “rx” refers to the corner radius of the rectangle element. The attributeName specifies the target property to animate. That property can be either a css style, or an svg property of the element. You can even add multiple animate elements affecting different properties to the same graphic element.

You can also add an animateTransform element to any graphic element. This will allow you to animate transformations to the element, such as scaling and rotation.

<svg viewBox="0 0 46 80">
<g>
<rect class="cls-1" x="8.58" y="6" width="38" height="38" transform-origin="27 27">
<animate attributeName="rx" values="0;20;0" dur="2s" repeatCount="indefinite" />
<animateTransform attributeName="transform" type="rotate" from="0 0 0" to="360 0 0" dur="3s" repeatCount="indefinite" />
</rect>
<rect class="cls-1" x="8.58" y="29.58" width="38" height="38" transform="translate(-26.27 33.73) rotate(-45)"/>
</g>
</svg>
Rotating the upper diamond while changing corner radius

As you can see from the demo, this allows you to get some complex effects very easily, as long as you understand how to control the different elements svg supplies.

<svg viewBox="0 0 46 80">
<g>
<rect class="cls-1" x="8.58" y="6" width="38" height="38" transform-origin="27 27">
<animate attributeName="rx" values="0;20;0" dur="2s" repeatCount="indefinite" />
<animateTransform attributeName="transform" type="rotate" from="0 0 0" to="360 0 0" dur="1.5s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0;1;0" dur="4s" repeatCount="indefinite" />
</rect>
<rect class="cls-1" x="8.58" y="29.58" width="38" height="38" transform="translate(-26.27 33.73) rotate(-45)">
<animate attributeName="fill" values="#f00;#0f0;#00f;#f00" dur="4s" repeatCount="indefinite" />
</rect>
</g>
</svg>
Adding opacity and fill color changes

You can animate just about every element, group, property and style of an SVG. This kind of animation is also a subset of SMIL, which stands for Synchronized Multimedia Integration Language.

So far, so good. But we can go a step further, because you can also use css animations to make svgs move in even more mysterious ways. For example, by adding this code to the css:

@keyframes stroke-draw {
from {
stroke-dashoffset: 12;
}
to {
stroke-dashoffset: 0;
}
}
.cls-2{
fill:#f00;
stroke:#231f20;
stroke-miterlimit:10;
transition:all 0.5s linear;
stroke-dasharray: 6;
stroke-dashoffset: 6;
animation: stroke-draw 0.5s linear alternate infinite;
}

and giving the second diamond the class cls-2, it makes the dashes crawl around the edge of the shape.

You can also control the animations and css with javascript to take it to yet another level. Take a look at the Github repository, and feel free to download and play with the code. You don’t need to use Vue, and the repository also contains a folder with the demos just as embedded SVG files too.

What I’ve shown just scratches the surface with very simple graphics. You can animate along a path and create interactive elements of all kinds. Combining javascript with svg allows you to create almost anything you can imagine in a web page, even complex 2D games and very slick custom interfaces. By avoiding bulky graphics, pages built with these techniques load quickly even on the slowest network. Searching for SMIL and SVG animation tutorials around the web will let you explore a lot more ideas.

--

--