Hope Armstrong Product Designer at Treehouse. Animal advocate. Vegan. Painter. Former troll collector. Into lowering waste 🌏

How to animate SVG with CSS: Tutorial with examples

8 min read 2381

Css Svg Animate Nocdn

Editor’s note: This article was last updated 12 July 2022 to include additional examples.

Web animations are a delight, improving the user experience by providing visual feedback, guiding users through tasks, and jazzing up websites overall. There are several ways to create web animations, including using JavaScript libraries, GIFs, embedded videos, and CSS.

In comparison to bulky gifs and videos, animations added to websites using SVGs and CSS have a faster load time. You can also make simple animations without having to add another JavaScript library to your website’s page load.

In this article, we’ll learn how to create lightweight, scalable animations using SVGs with CSS. Although we’ll use Sass for the demos, CSS will also work. Let’s get started!

Common use cases for animating SVG with CSS

Before we jump into the code, let’s review some practical ways to use animated SVGs.

Icons

Animated SVGs are great for icons that indicate micro-interactions and state changes. They are also helpful when guiding a user to the next action, like in an onboarding tour. Common use cases include loading, uploading, menu toggling, and playing and pausing a video.

Illustrations

Illustrations are another common use case. They can be included in a product as a blank state, demonstrating what to do to generate data on a dashboard. Other popular use cases include animated emojis and stickers. There are also animated spot illustrations, which help to brighten up landing pages.

How to prepare SVGs for animation

Since it’s easier to start out with simplified SVG code, the first part of animating SVGs is preparing them. You can do so by following the steps below:

Optimize the SVG code

When an SVG is created, it often has some extra, unnecessary code, so it’s important to optimize it. You can use a tool like SVGOMG that reduces the file size and removes any unnecessary tags and metadata.



Create intentional groupings

If needed, you can create intentional groupings by opening the SVG in a code editor and taking note of the <g> elements, which are used to group SVG elements. If you want to animate a group of elements together, wrap them in <g></g> and name them with a class or ID.

If we want to style multiple paths in the same way, we could also consider converting ID names to class names.

Beware of stacking order

It seems counter-intuitive, but shapes listed last will be pasted over the aforementioned shapes. If we want a shape to appear in the background, we must ensure that it is listed at the top of the SVG code. SVG shapes are painted in order from top to bottom.

Set SVG styling to the preferred, initial state

SVGs have presentation attributes that are similar to CSS styles but are set directly on the SVG. A common example is a fill color. Since these styles are set on the SVG, you may assume that they hold a lot of weight by the browser. As it turns out, any CSS or Sass we set externally will naturally override the SVG styling without a need for an !important declaration.

However, be mindful of what is set on the SVG so you can prepare for what’s shown during page load. For example, a slow-loading page will display a flash of the SVG before the CSS styles get applied. I recommend you leave in the width and height to avoid this; Sara Soueidan does a good job of explaining flash of unstyled SVGs in her blog post on the subject.

Applying CSS to SVGs

Now that we’ve tidied the SVG, let’s explore a few options for adding the CSS.

There are a few considerations when it comes to applying CSS to an SVG. One limitation is that we can’t use an external stylesheet to apply styling to an externally linked SVG.

Embedding the SVG code inline in the HTML makes the SVG element and its contents part of the document’s DOM tree, so they’re affected by the document’s CSS. This method is my favorite because it keeps the styles separate from the markup.

In reviewing the other options below, we’ll see they’re all entwined. If you’re using Rails, there are some gems that can automatically embed SVGs into views. So, in your code, you can simply reference the external SVG, then it’ll get embedded when compiled. An added benefit of this method is that inlining the SVG means there’s one less HTTP request, improving performance:

We can add CSS styles in a <style> tag, nested within the <svg> tag:

See the Pen
SVG – 2
by Luke Tubinis (@lukelogrocket)
on CodePen.

If you’d like to keep the styling referenced in the SVG, but not actually include it within the SVG, you can use the <?xml-stylesheet> tag to link to an external style sheet from the SVG:

See the Pen
SVG – 3
by Luke Tubinis (@lukelogrocket)
on CodePen.

CSS may also be set on an element using inline style attributes


More great articles from LogRocket:


See the Pen
SVG – 4
by Luke Tubinis (@lukelogrocket)
on CodePen.

What can you animate with CSS?

You can animate lots of things with CSS. For one, you can animate CSS properties with values that can change over time using CSS animations or CSS transitions. For a full list of these properties, check out the MDN Web Doc for a list of animatable CSS Properties. To spark some inspiration, let’s review a few demos.

There are two main types of animations we’ll cover, and they differ by the amount of control they provide.

Rotating loader

The first SVG animation we’ll create is a rotating loader, like the ones we usually see on the loading screens of applications. We start by setting up the SVG, which is a ring with a darkened quadrant.

We give the SVG an ID of loading-spinner, then define the animation and transition. The animation references the name of the @keyframes, where the transform: rotate is set to go from 0 degrees to 360 degrees, a full rotation. That’s all it takes to make this spinner come to life!

#loading
  animation: loading-spinner 1s linear infinite

@keyframes loading-spinner
  from
    transform: rotate(0deg)
  to
    transform: rotate(360deg)

Sass

Wanting something smoother? SVGs support gradients, so you can achieve a smoother effect using the same Sass but with an SVG that has a gradient applied to the ring, see it defined as #spinner-gradient-a below:

See the Pen
Rotating Loading SVG Icon with Gradient Animated with CSS / Sass
by Hope Armstrong (@hopearmstrong)
on CodePen.

Now, let’s play around with transform: scale to create this morphing bar loading icon.

See the Pen
SVG Loading Bars Animated with CSS / Sass
by Hope Armstrong (@hopearmstrong)
on CodePen.

The SVG consists of three equally sized rectangles spaced apart evenly. IDs have been added per element,  for the SVG and all three <rect> elements, so they can be easily targeted with the Sass.

HTML

The Sass applies the animation to each bar. The keyframes tell the bars to change scale along the Y axis in four places in the timeline : on onset, a quarter of the way in, halfway, and then three-quarters of the way in.

The first number in the animation denotes the animation length, while the second one sets the delay. Since I want these bars to morph in size at different times, I’ve added different delays for each:

#loading-bar
  &-left
    animation: loading-bar-morph 1s linear .1s infinite
    transform-origin: center
  &-middle
    animation: loading-bar-morph 1s linear .2s infinite
    transform-origin: center
  &-right
    animation: loading-bar-morph 1s linear .4s infinite
    transform-origin: center

@keyframes loading-bar-morph 
  0%
    transform: scaleY(1)
  25%
    transform: scaleY(0.3)
  50%
    transform: scaleY(0.7)
  75%
    transform: scaleY(0.15)

Note that transform-origin: center tells the transform to scale from the center of the bar; otherwise, it would scale from the top down and appear as if the bars are drilling into the ground. Test it out, and you’ll see what I mean.

By default, an SVG is positioned at the (0, 0) point, in the top-left corner. This is a key difference if you’re used to working with HTML elements, whose default transform-origin is always at (50%, 50%).

Line drawing animation

We can add a line-drawing effect to make the SVG appear as if it’s being drawn. Since it relies on strokes, it requires an SVG with lines. I’ll walk you through how it’s done for a single line, and then you’ll know how to do the rest.

First, apply a dashed stroke to the lines using stroke-dasharray. The number represents the length of the dashes in pixels. You’ll want it to be the length of the line:

#line
  stroke-dasharray: 497

Then, add stroke-dashoffset to reposition the dash along the line. Make it as long as the line itself so it looks like a solid line. This is how the final frame of the animation will look:

#line
  stroke-dasharray: 497
  stroke-dashoffset: 497

Now, it’s ready to be animated. Let’s add keyframes that animate the stroke-dashoffset so it goes from the full offset with no stroke visible to a 0px offset, a solid stroke. Note the forwards in the animation property.

This is an animation-fill-mode that tells the animation to stay in its final end state once played. Without it, the animation would then return to its first frame as its final resting spot:

#line
  stroke-dasharray: 497
  stroke-dashoffset: 497
  animation: draw 1400ms ease-in-out 4ms forwards

@keyframes draw
  from
    stroke-dashoffset: 1000
  to
    stroke-dashoffset: 0

Animated illustration

Let’s use Animista’s heartbeat animation to demonstrate animating an illustration to have a pulse effect. Animista is a great resource for premade CSS animation effects that you can reuse and iterate on.

For this beating heart, a few animations are triggered on hover. There’s a 110 percent scale change on the heart, and the eyes get smaller, the mouth gets bigger, blush appears, and the heart pulses:

#smiley-love
  #smiley
    &-blush
      display: none
  a
    display: inline-block
    &:hover
      #smiley
        transform: scale(1.1)
        transform-origin: center
        -webkit-animation: heartbeat 1.5s ease-in-out infinite both
        animation: heartbeat 1.5s ease-in-out infinite both
        &-blush
          display: inherit
        &-eye-left
          transform-origin: center
          transform: scale(.7) translate(-8px)
        &-eye-right
          transform-origin: center
          transform: scale(.7) translate(8px)
        &-mouth
          transform: translateY(-22px) scale(1.6)
          transform-origin: center

/* ----------------------------------------------
 * animation heartbeat
 * Generated by Animista on 2019-3-24 18:51:13
 * w: http://animista.net, t: @cssanimista
 * ---------------------------------------------- */

@-webkit-keyframes heartbeat
  from
    -webkit-transform: scale(1)
            transform: scale(1)
    -webkit-transform-origin: center center
            transform-origin: center center
    -webkit-animation-timing-function: ease-out
            animation-timing-function: ease-out
  10%
    -webkit-transform: scale(0.91)
            transform: scale(0.91)
    -webkit-animation-timing-function: ease-in
            animation-timing-function: ease-in
  17%
    -webkit-transform: scale(0.98)
            transform: scale(0.98)
    -webkit-animation-timing-function: ease-out
            animation-timing-function: ease-out
  33%
    -webkit-transform: scale(0.87)
            transform: scale(0.87)
    -webkit-animation-timing-function: ease-in
            animation-timing-function: ease-in
  45%
    -webkit-transform: scale(1)
            transform: scale(1)
    -webkit-animation-timing-function: ease-out
            animation-timing-function: ease-out
@keyframes heartbeat
  from
    -webkit-transform: scale(1)
            transform: scale(1)
    -webkit-transform-origin: center center
            transform-origin: center center
    -webkit-animation-timing-function: ease-out
            animation-timing-function: ease-out
  10%
    -webkit-transform: scale(0.91)
            transform: scale(0.91)
    -webkit-animation-timing-function: ease-in
            animation-timing-function: ease-in
  17%
    -webkit-transform: scale(0.98)
            transform: scale(0.98)
    -webkit-animation-timing-function: ease-out
            animation-timing-function: ease-out
  33%
    -webkit-transform: scale(0.87)
            transform: scale(0.87)
    -webkit-animation-timing-function: ease-in
            animation-timing-function: ease-in
  45%
    -webkit-transform: scale(1)
            transform: scale(1)
    -webkit-animation-timing-function: ease-out
            animation-timing-function: ease-out

 

Let’s do another; for this example, I animated the drops on this image of a popsicle by changing their position using transform: translate. To make them disappear, I animated the opacity. Now, it looks like it’s a hot summer day!

See the Pen
Melting Popsicle SVG Animated with CSS / Sass
by Hope Armstrong (@hopearmstrong)
on CodePen.

Hamburger menu

Let’s create a hamburger menu using SVGs; the animations will be triggered when a user hovers over the menu:

See the Pen
Animated SVG Hamburger Menu
by Emadamerho Nefe (@nefejames)
on CodePen.

Let’s break down the code above. First, we set up a hamburger SVG with the rect element and drew three rectangles. We gave the three rect elements classes of top, middle, and bottom, respectively.

The core of the animation takes place on hover. When a user hovers, we alter the positions of the rectangles and rotate the top and bottom rectangles by 45 percent and -45 percent, respectively. We also set the opacity of the middle rectangle to 0.

Fade-in and fade-out text

Another cool animation is a fade-in and fade-out text animation:

See the Pen
Fade-in SVG Text
by Emadamerho Nefe (@nefejames)
on CodePen.

Here, we set up an text-based SVG using the text element, defined a fadeIn animation that will toggle the opacity of the text between 0 and 1, and applied the fadeIn animation to the SVG.

Wavy SVG text

The final demo is a wavy text animation where each letter in the world will go up and down to look like the motion of a wave. We could also call this animation a bouncy text animation.

See the Pen
Wavy SVG Text Animation
by Emadamerho Nefe (@nefejames)
on CodePen.

For the SVG, we use the text element to define each letter of the word wavy. We push the letters down by 3px with translateY. Later, we’ll make it pop up as part of the wave motion. To complete the effect, we define an animation called wavyText, and we delay the animation of each letter so they pop up one after the other.

Other tools for animating SVGs

While we can animate SVGs with CSS, there are other tools we can use to handle and create animations. SVG animations can get a little complicated, but the following tools make it extremely simple for us to animate SVGs.

Conclusion

Now that you know a few different ways to animate SVGs with CSS, I hope you’re inspired to create your own animations for the web! It’s fun to bring static SVGs to life with just a few lines of CSS.

Once you get the hang of a few tricks, it’ll be easier to tackle the more complicated animations. There are endless amounts of inspiration online and on sites like CodePen. Happy animating!

Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.https://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web and mobile apps — .

Hope Armstrong Product Designer at Treehouse. Animal advocate. Vegan. Painter. Former troll collector. Into lowering waste 🌏

8 Replies to “How to animate SVG with CSS: Tutorial with examples”

  1. Hi, Hope!

    Thank you for sharing with us your tips on creating SVG with CCS and LogRocket tool! We’ll give it a try.

  2. the main problem I’ve encountered with SVG animations powered by CSS is that at some point the animation stops and web page “gets heavy”.

Leave a Reply