animated svg icons
October 28, 2014 | 32 Feedbacks

Animated SVG Icon

How to optimize SVG code and animate an SVG icon using CSS and Snap.svg library.
Browser support
  • ie
  • Chrome
  • Firefox
  • Safari
  • Opera

Working with SVG files is not an option anymore. With a huge amount of high definition devices out there, it’s not sustainable to export different sizes of the same bitmap assets and target specific device resolutions through CSS media queries. We need to rely on vector graphics whenever it’s possible.

Today’s resource is a very simple icon, that we imported as inline SVG into our index.html file. After having optimized the svg code, we tried to push it one step further by animating the icon using CSS and Snap.svg, which is a javascript SVG library created by the Adobe team. To be honest, it’s not that easy to animate svg files with the current browsers support status quo, but we learned some tricks along the way that we’re happy to share with you!

If you’re new to SVG, here are some great resources to start with:

Creating the SVG

The easiest way to create an SVG illustration is to use graphic editors such as Adobe Illustrator or Sketch. Pick the one you prefer and create an icon (or download our source file). Most of what you create in these apps is SVG friendly, meaning that the graphics you create can be translated into code. The easiest way to realize that is to save an icon as .svg file, then open it with a code editor.

Take in mind, though, that the way you organize your layers in your graphic editor is gonna affect the code output.

To make you an example: since our final icon is animated in 2 steps, I created 2 separate layers in Illustrator, one for the loading effect and one for the buildings. Since the visibility of the cd-buildings layer is turned off, I can expect a display:none applied to that element in the output code. Also, layers and groups in Illustrator are considered groups in the SVG code exported (which is a good thing). Layer titles in AI will be assigned as #id values in the SVG code.

SVG file in Illustrator

While exporting .svg from AI, default settings work just fine. I just make sure that CSS Properties is set to Style Elements, in order to separate style from content – AI automatically creates classes.

SVG save settings in AI

Some points to take in mind while creating SVGs in a graphic editor:

Optimizing SVG code

I personally don’t use tools to automatically clean up SVG code for me. Since I always start from the graphic editor, I found out the best way to export clean code is to be thorough while designing – and following the tips I suggested before.

Once the .svg file has been exported, let’s import it into a code editor and take a look at the code:

As you can see, Illustrator created some classes for us. Also, the structure is pretty clean already. By giving a name to groups and layers in AI, we can now easily find them in the SVG coding structure.

First of all, since we want to include this graphic as inline SVG, we can grab only the code wrapped into the <svg></svg> tags and paste it into an .html file.

I’m working with a HTML5 document, so I can remove the namespace declaration and add a title and description to improve the file accessibility.

Next step is to create more semantic classes in CSS to replace the ones created by Illustrator. The icon is quite minimal, therefore the CSS is gonna be just few classes:

Yes, we can modify SVG presentation attributes inside our CSS file! We can now delete the style from the SVG code and assign the classes accordingly to the elements.

Also, I did some changes to the structure: I moved some elements down in the SVG structure, the reason being that the lower an element is in the structure, the higher its z-index. Finally I changed some coordinates as well – very small details, like moving elements couple of pixels around if they weren’t perfectly aligned. You know, unnecessary stuff designers love to waste time with.

The SVG is almost ready to be animated. I wrapped the <svg> element into a container (.cd-svg-container) to align the icon into the center. Setting a max-width:100% will make the SVG responsive (just like images). Also you may notice an overflow:hidden applied to the SVG: it’s because we will animate the clouds in and out the canvas, and for some unknown reasons IE shows them even when they are out, unless we apply the overflow property.

Also you may notice a rectangle (.cd-pointer) inside the #cd-pause-btn element. It’s used to make the area between the 2 pause rectangles clickable, hence the opacity:0 and the fill value.

We defined a .cd-fade-out class to be applied in javascript at the end of the loading animation to the #cd-loading element.

Finally we used the .no-js class in case javascript is disabled: as fallback we don’t show the loading icon, but the buildings (it just makes more sense).

Animating the SVG

We decided to animate our svg using JavaScript rather than SMIL in order to support Internet Explorer (if you are interested in the SMIL technique check out this guide by Sara Soueidan).
In our animation, we wanted to initially hide the #cd-buildings group. To do so, we modified some attributes in the svg code.
As an example, let’s focus on the #cd-home-1-door rectangle element (which is the door element of the first house on the left). We wanted this element to be hidden at the beginning and then animate its height from 0 to 28px. So, in the HTML structure, we set the height = "0" (instead of height="28") and add a data-height = "28"  to easily retrieve it with JavaScript.

We used the animate() method provided by Snap.svg

The door expands from top to bottom, but we wanted the opposite effect! So we applied a 180deg rotation to the element.

One important note: at the beginning we tried appling a CSS rotation (rather than using the svg transform attribute), but unfortunately CSS transformations on SVG are currently not supported in IE11 and below.

The rotate() function accepts three parameters: the first one is the angle of rotation, the second and the third ones the coordinates of the center of rotation.

Once all the elements of the #cd-buildings group have been hidden, we focused on the #cd-loading. First, we wanted to hide the #cd-pause-btn. We assigned it a scale transformation:

One important note: the scale() function doesn’t accept, as argument, the transform origin coordinates (the default one is the svg upper-left corner). To scale an object by a given factor around a point, you can combine two transformations:

Since in our case factor=0 and (centerX, centerY) = (100, 100), we applied also a translate(100 100) transformation.

After that, we needed to animate the #cd-loading-circle-filled element (crimson circle which is drawn when you click the play button). To create this animation, we used the two svg attributes stroke-dasharray and stroke-dashoffset. Imagining the circle as a dashed line, the stroke-dasharray lets you specify dash length and gaps, while the stroke-dashoffset lets you change where the dasharray starts. In our case we set:

This way, the dash and gap are both equal to the circle circumference, but we set stroke-dashoffset: circumf so that only the gap (transparent) is visible. To create the loading effect, we animated the stroke-dashoffset attribute:

One important note: the stroke-dashoffset attribute for a circle element cannot be animated using the animate() method directly (while it works fine for a path element); this is why we have been using the Snap.animate() method and stored the returned animation object in the globalAnimation variable in order to stop the animation when user clicks on the pause button:

Once the circle animation is completed, we start animating the buildings and the clouds using the technique described at the beginning of this paragraph.

That’s it! Hopefully browsers support will get better soon, and we will rely on SVG technology not only to create scalable graphic elements, but also complex animations ;)


Oct 28, 2014
  • Resource released by CodyHouse

Sebastiano Guerriero

UI/UX designer, with a huge passion for Nutella. Co-Founder of CodyHouse. You can follow him on Twitter or Dribbble.

  • Mate Brkić

    This is cool, but I am sad that we need this amount of code to achieve this.

    • Sebastiano Guerriero

      I see your point @matebrki:disqus. One thing to consider though: you can create a subtle animation, maybe focused on a detail only (no need to have jumping buildings etc), and the code won’t be that much at all. We tried to cover most user cases here, but you can play with svg animations in a much simpler way

      • Shaun Dona

        It would be good to see a very simple version with one element moving available from the download package.

        Great work btw!

  • Colton Fitzgerald

    This is awesome! You guys never fail to impress!

  • Jayme Ayres

    Awesome! Congrats!

  • Andy Miller

    Thanks for another great piece of work.

    If you don’t have Illustrator, but you do have a Mac, then Affinity Designer ( )is well worth checking out (there are a number of other new vector editors on Mac, but my favourite is AFD). It doesn’t yet produce files with the CSS separated out, but SVG Optimiser ( ) will do that quickly and easily. (I agree with what you say about avoiding the need to use an optimiser, but it seems to do a pretty good job).

  • Daniel O’Connor

    At what point do you think it is best to use a library like Snap.svg instead of relying on CSS animations and SMIL?

    • Sebastiano Guerriero

      The great advantage of using Snap is browser support. If the animation is vital to understand the SVG/illustration meaning, I’d say go for Snap. Also for complex animations, Snap makes things easier for you (you can’t animate height and width of an SVG using CSS).
      If you’re animating small icons, I’d use SMIL or CSS. The advantage of CSS is in case the animation is the same for all icons: you can change all the animations at once with one class. Browser support is still not great, but you can provide a fallback image.
      So I’d say the keys are 1) complexity and 2) animation relevance. The higher the two of them, the more I’d go for Snap.

      • Daniel O’Connor

        Yeah. Unfortunately I’ve recently been learning about these weird browser inconsistencies the hard way!

  • roblevintennis

    Sebastiano, that’s a sweet example thanks! I’m curious what your thoughts are comparing snap to velocity.js? A coworker of mine mentioned he had a lot of trouble with snap (could just be heresay I suppose), but I was tinkering with velocity.js and it looks pretty solid. Anway, thanks again for the tut man!

    • Sebastiano Guerriero

      Velocity is great, we used it for another resource ( Snap is totally focused on SVG though (i.e. I don’t think there’s a way to animate paths using velocity). Based on my experience it’s not Snap that has lots of troubles, while it’s browsers handling SVG in different ways, with still lack in supporting main features.

      About “Thinking with animations”, I personally did a motion design course, then started experimenting with After Effect to learn the basics (which helped a lot!). I never studied Flash either.


      • roblevintennis

        Sebastiano, the velocity less focused comment seems reasonable; also thanks for letting me know your “thinking animations” background. Yeah, I’m going to keep tinkering with examples like yours but maybe a motion design course / aftereffects like you mention would be helpful too.

        • roblevintennis

          I’m not too familiar with snap.svg yet, but I was a bit surprised that you had to have all the setTimeouts with nesting to keep the chain going…there’s no way to use some sort of method chaining with snap.svg?

  • Elancore

    OMG I miss the days of Flash, I would do same animation in 1 min and without any code.

    • Aimen Zenasni

      Sometimes, i miss Flash too :(

      • Jeremy Nusser

        Flash is still apart of the Creative Cloud still.

        • Ben Debnam

          and you can export html5 canvas animations from it – not always the best solution but handy

  • subir pal

    Thanks for the nice article. All of your works are very impressive. I would like to use this Animate SVG as a intro of a realty website. I m trying to remove the play button from beginning, just play the animated house and then redirect to home page. But no luck… So is there any way to to this.

    Thanks for ur great effort.

    • Claudia Romano

      Hi Subir, glad you liked it! :)
      You should try removing the #cd-loading group from the .html file. Then, in the js file, replace initLoading(); (right after the var globalAnimation declaration) with animateFloor();

      I have not tested it but should work. Cheers!

      • subir pal

        Thanks Claudia for replying. I did it as per your suggestion, but its not working. :(

  • Johannes Mutter

    Is it possible to animate the »d« attribute of a path with Snap.svg like we can with SMIL? (e.g. for morphing paths)

    • Claudia Romano

      Yes, you can do that using the animate function.

      • Johannes Mutter

        Thanks a lot. Works like a charm. Also a big »Thank you« to you and Sebastiano. Your articles and resources are great insights. Merry Christmas!

  • Lam Allthephoto


  • labadz

    I love this tutorial. How would one go about implementing the SVG’s animation on hover, instead of with the play button?

    • Claudia Romano

      Hi, glad you like it!:)
      You should try using the .hover() method rather than the .click() one.

  • Kao

    Great tutorial thank you so much.
    One thing i am still confused is how do i find out center point of transform-origin to set on my SVG (absolute values)?
    Can we use the same formula as translate() you mentioned above?

    • Claudia Romano

      Hi Kao, yes you can use the same formula with your svg parameters (our svg viewbox is (0, 0, 200, 200) so the center is gonna be (100, 100)).

  • Tom Lynch

    Love this, I’ve seen a few implementations of this about (particularly on the Amber Creative page!) and they look really amazing!

    It’s moved right to the top of my “to mess about with” list now! Great article as always

  • sandeep sharma

    Awesome Brother

  • Fil IP

    You’re now officially my hero.

  • fsidc

    To me, it seems SVG icons are missing some features to really overcome font icons.. With your technique we are able to change the color, same as icon fonts, nothing else? No way to animate, or to change only a custom svg path?
    The only pro I can see is that this way we keep a visual connection between the original images (the svg itself) and the spritesheet. It is not just some crazy binary file format that translate into icons..
    Too much trouble, you can download this free svg icon.