Grow your CSS skills. Land your dream job.

Animating SVG with CSS

Published by Chris Coyier

There isn't just one way to animate SVG. There is the <animate> tag that goes right into the SVG code. There are libraries that help with it like Snap.svg or SVG.js. We're going to look at another way: using inline SVG (SVG code right inside HTML) and animating the parts right through CSS.

I played with this personally recently as my Alma mater Wufoo was looking to freshen up the advertising graphic we're running here. My latest design around here uses SVG quite a bit and I thought this would be another perfect opportunity to use it some more.

The finished product is pretty simple. Here's it is:

See the Pen Wufoo SVG Ad by Chris Coyier (@chriscoyier) on CodePen.

Let's check out how it's done.

1. Design the Ad / Have a Plan

This might seem like an how to draw an owl moment, but this article is about animation so let's get there as quickly we can.

My plan for this ad was to make a super simple Wufoo ad with their classic logo, colors, and general branding. Then add a little flair.

  1. Make the letters kind hop off the page a little. Wufoo is a fun word, let the letters have some fun.
  2. Back in the day we made a T-Shirt with dinosaurs on the front and on the back it said "Fast. Smart. Formidable." Which are traits of both dinosaurs and Wufoo, not to mention the fun little play on words with FORMidble. Let's make those fade in and out.
  3. To make the connection with the dinosaur thing complete, we'll have a T-Rex head pop up from the bottom curiously, then zoom away. The word "Fast." will come in as he zooms away which is another nice little connection.

I put all the parts together in Illustrator.

Notice how the logo and tagline text are outlines. That means they are just vector shapes and will render just perfectly as-is in the SVG, as <path>s. The text you see there "Fast." is left as text in Illustrator.

When I save this out from Illustrator, that will be left as a <text> element.

2. Save as SVG

Illustrator can save this directly as SVG:

You can open that SVG file in a code editor and see the SVG code:

3. Clean Up the SVG, Give Shapes Classes

You might wanna run it through SVGO to optimize it and remove the DOCTYPE and stuff. But more importantly for this post, you'll want to give the the different shapes class names, that way we can select them in CSS and do stuff!

<svg version="1.1" id="wufoo-ad" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 400" enable-background="new 0 0 400 400" xml:space="preserve">

  <!-- background -->
  <rect class="wufoo-background" fill="#D03E27" width="400" height="400" />

  <!-- logo letters -->
  <path class="wufoo-letter" fill="#F4F4F4" d="M60.858,129...." />
  <path class="wufoo-letter" fill="#F4F4F4" d="..." />
     <!-- etc -->

  <!-- dinosaur -->
  <g class="trex">
     <path ... />
     <path ... />
  </g>

</svg>

4. Insert the SVG

You can copy-and-paste that SVG right into the HTML where you want the ad. But that'll just slop up the template probably. In all likelihood you'll just do something like:

<aside class="sidebar">
  
   <div class="module module-ad">
      
       <?php include("ads/wufoo.svg"); ?>

   </div>

   ...

5. Animate!

Now we have these shapes in the DOM that we can target and style like any other HTML element, let's do that.

Let's say we want to do this as a 10 second timeline.

Words Fade In/Out First

The first thing we want to happen is the Fast. Smart. Formidable. thing. Each word will show for one second. So we'll make an animation where the word shows for 10% of the time:

@keyframes hideshow {
  0% { opacity: 1; }
  10% { opacity: 1; }
  15% { opacity: 0; }
  100% { opacity: 0; }
} 

Then target that first word and have the animation last for 10 seconds (10% of that is 1 second):

.text-1 {
  animation: hideshow 10s ease infinite;
}

The next two letters will start out hidden (opacity: 0;) and then use the exact same animation, only delayed to start a bit later:

.text-2 {
  opacity: 0;
  animation: hideshow 10s 1.5s ease infinite;
}
.text-3 {
  opacity: 0;
  animation: hideshow 10s 3s ease infinite;
}

The extra 0.5s on each is to accommodate the fading out time period of the word before it.

Letter Pops

As soon as those letters are done animating, we'll have the letters in WUFOO do their jiggle jump thing, like this:

The trick here is that we'll make the animation only 5 seconds long, but run it once forwards and once backwards. That way it matches our 10 second timeline, is placed right in the middle where we want it, and we only need to scale in one direction, because when it reverses it will scale back.

Each letter has a slight bit of delay so they happen off-kilter a bit:

.wufoo-letter {
  animation: kaboom 5s ease alternate infinite;
  &:nth-child(2) {
    animation-delay: 0.1s;
  }
  &:nth-child(3) {
    animation-delay: 0.2s;
  }
  &:nth-child(4) {
    animation-delay: 0.3s;
  }
  &:nth-child(5) {
    animation-delay: 0.4s;
  }
}
@keyframes kaboom {
  90% {
    transform: scale(1.0);
  }
  100% {
    transform: scale(1.1);
  }
}

The above is in SCSS just for brevity, and does not include any prefixing (as you would need in production).

I feel like animation-delay is a property that would benefit from native randomization in CSS. Would be neat to see the letters be randomly delayed just a bit each time.

Dinosaur Last

As soon as the words are done, the dinosaur will peak its head up. Even though the dinosaur is made up of lots of <path>s, we can target them all together by targeting the <g> (group) tag that wraps them all.

Because using translate to animate position is better, we'll do that in the keyframes:

@keyframes popup {
  0% {
    transform: translateY(150px);
  }
  34% {
    transform: translateY(20px);
  }
  37% {
    transform: translateY(150px);
  }
  100% {
    transform: translateY(150px);
  }
}

We wanted this animation to "last" about 3 seconds. It actually runs in 10 second loops, but you'll only see it do stuff for 3 seconds. When the translateY(150px) is in effect, the dinosaur is moved so far below, you don't see anything. By 37% of that animation (around 3 seconds) you'll have seen it move slowly up, then quickly back down).

When we apply this animation, we'll make sure that:

The dinosaur is hidden at first
The animation is delayed so it starts right after the words are done with their fade in/out dance.

.trex {
  transform: translateY(150px);
  animation: popup 10s 6.5s ease infinite;
}

The dinosaur pops down right at the last second, which is when the word "Fast." pops back onto the screen (because all the animations are set to infinite, which re-runs them forever). That's a bit of fun synergy there.

6. Making it a responsive / clickable ad

One of the beautiful things about SVG is that it's scaleable to any size without losing quality. To make an inline SVG like this scale while maintaining its aspect ratio, we can use the ol' padded box technique.

<div class="wufoo-ad-wrap">
  <svg class="wufoo-ad">
     ...
  </svg>
</div>
.wufoo-ad-wrap {
  height: 0;
  padding-top: 100%;
  position: relative;
}
.wufoo-ad {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

The idea here is that the "wrap" will always be a perfect square, relative to its width. Then we absolutely position the SVG within that perfect square, which will happily resize itself.

Since this is an ad (which of course should be clickable), rather than using a <div> for the wrap, you could use an <a href="">, just make sure you set that to be display: block;.


Final thing, for reference.

I think there is a future for this kind of thing in display advertising, particularly because of the CSS control and easy, sharp resizing.

Comments

  1. Animating with CSS has always been an issue because it’s percent based and not time based. This is one of the reasons why GSAP is so popular. SVG animation (SMIL) on the other hand does a pretty good job but has no support in IE at all. I’m in the process of writing smil2css to circumvent this problem. It essentially converts SMIL to CSS animations, much like your article is suggesting.

    • Amelia BR
      Permalink to comment#

      Sounds neat, but it won’t help with current versions of IE — they don’t support CSS animations applied to SVG, either.

    • I haven’t tested with IE11 yet as I don’t have Win8, but it works fine in IE10 on Win7. There are a lot of browser issues with SVG right now. This one, for example still needs to make its way into a Chrome release.

    • IE Vendor prefix not support?

  2. Permalink to comment#

    Never thought about using SVG as a code snippet; always just linked to them like I would a regular png or jpg. Now I can see how easy it is, I’m going to be using them like this all the time.
    Great little tutorial, Chris. Thanks!

    • You can also load them with background-image, which my favourite way.

    • Permalink to comment#

      Good tip, Steven. Can you still target the class and id parameters in your CSS if you load them using background-image?

    • Tom, I haven’t tested it, but I’d imagine that when the SVG is loaded in as a style asset, it cannot access its parent document’s stylesheet. It will definitely work, though, if you embed the relevant CSS into a <style> within the SVG file.

  3. Permalink to comment#

    Good post! Thanks for the tips.

    I was messing around with SVG / CSS animation last week and it took a while to figure out the syntax. Though I did manage to implement a variation of the popular “line drawing” animation: http://codepen.io/shshaw/pen/JDEsG

    My main struggle was with how to handle the animation-delays for individual elements in an elegant way, but by separating out the different stages of the animation ( line drawing, stroke fade out, fill fade in ), I was able to stagger the elements’ animations the way I wanted.

  4. Unfortunately only the three words animate on chrome mobile. The dinosaur and wufoo do not, or is this intended?

  5. Nice work! I’ve been doing a lot of SVG animation lately, good to keep this technique in mind. Another advantage: you can tweak the animation for different screen sizes using media queries. Can’t do that with just inline SVG animations, as far as I know.

    • SVG animations (SMIL) can animate CSS properties, so you can animate with percent values. Media queries might get a bit messy for positioning, but would work fine for hiding/showing. It’s give and take, really, because CSS can’t do everything that SMIL can. One example would be animating along a path.

  6. Why U re not coloring with classes?

    You can remove fill=”FFFFFF” and make it like this

    svg
       .class
          fill: #FFFFFFF
    
  7. This is the thing I’ve been trying to learn from last couple of months but its quite complex :(

  8. Martin
    Permalink to comment#

    I’ve used this illustrator technique to create svgs, which also spits out a doctyoe for the svg. I’m under the assumption that this is needed. Am I correct in my thinking?

    • Sounds like you are trying to optimize the file size of your SVG file. If so, you might want to take the shortcut and just run it through SVGO.

    • Amelia BR
      Permalink to comment#

      Illustrator (and Inkscape) creates stand-alone SVG files that are fully XML compliant with doctypes and namespaces.

      If you’re only going to be using the image in the browser (and if your server is set to always give the correct MIME type for .svg files), you can usually skip the doctype. If you’re going to be cutting & pasting your code into an html5 page (or importing it server-side via php), then you can also skip the namespace declarations.

  9. Kris Bulman
    Permalink to comment#

    s/peak/peek/ :P

  10. Amelia BR
    Permalink to comment#

    Great step-by-step approach.

    One warning for anyone trying to use CSS animations and transitions with SVG: avoid the use of the “ element, or things become very buggy very fast!

    (that example focuses on CSS transitions and mouse events)

    (specifically on animations — not as buggy, but still inconsistent)

    • Amelia BR
      Permalink to comment#

      Urgh. The “ in the warning should be <use>. Must remember to use the preview option.

      P.S. Nice auto-embeds, Chris & co.!

  11. Expanding on what’s already been said, SVGs seem to be supported poorly on mobile browsers. Most of the SVGs on this site are completely blank squares over here on Mobile Safari (iOS 6.1.6) and animations seem to be right out.

    • Permalink to comment#

      SVG’s, including animated ones (both JS and pure CSS) work like a charm on my nexus devices (5 & 7). It also seems to work fine on the xcode iDevice simulator, though of course, that doesn’t say much ;).

  12. Very nice. Is there already a software that can easily generate the css code for you. Just select the animation you want, and poof! There you have it. Everything is neatly coded [HTML+CSS] after exporting/saving it. :D

  13. Sorry dummy question but not good in designing is illustrator is required or we can do this in photoshop too ?

    • Permalink to comment#

      because of the nature of SVG (Vector Graphics) you’ll need a program that can use and edit vectors straight out of the box; photoshop can’t. I’m sure there are other options than illustrator out there though!

    • Photoshop: No. You could use Inkscape, which is free and open source.

  14. Martin Lenngren
    Permalink to comment#

    This is great Chris, again! If your keyframe end (the 100% part) on the same position as it starts (the 0% part) you don’t need to define the end at all, that’s the default behaviour.

  15. I used this technique on a recent redesign of http://spigotdesign.com using a variety of transitions and transforms.

    Works great on most modern browsers. In Firefox it’s pretty ugly. Nice to see the Wufoo animates correctly in FF.

  16. Ooops, sorry! That should have read: …with <svg> elements wrapped in <a>-tags…

  17. lightnosugar
    Permalink to comment#

    You can save out of Illustrator CC with classes and IDs in the SVG code.
    CLASS: To give an object a named class, apply a Graphic Style with that name.
    ID: To apply an ID, name a layer what you want your ID and place your object on it.

    When you save your SVG file, go to “Advanced Options” and choose these settings:
    profile: SVG1.1
    CSS properties: Style Elements
    decimal places: 3
    Check the box for “Output fewer elements”
    Leave the rest unchecked

    When you open in a text editor, Illustrator will add inline styles which you can go in and delete, and instead use a CSS documnet to style.

  18. xy75
    Permalink to comment#

    define atomic reusable unstyled components
    group them into more complex components using “use” with styles and transformations
    clone complex components/whole svgs to achieve the independency

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".