Back to Blog
Tutorial8 min readUpdated July 6, 2026

How to Animate SVG Icons with CSS: A Step-by-Step Tutorial

Entrance effects, looping motion, hover triggers, and the classic "draw" effect — all with a few lines of CSS and zero JavaScript. Copy-paste examples included.

I

Icora Team

Engineering

An SVG icon being animated with CSS keyframes

SVG is markup, which means every shape inside it is a DOM element you can target with CSS. That single fact makes icon animation almost embarrassingly simple: no library, no runtime, no After Effects export pipeline. A few keyframes and you are done. This tutorial walks through the patterns that cover practically every icon animation you will ever ship.

Setup: Where the CSS Lives

You have two options. If the SVG is inlined in your HTML, animate it from your normal stylesheet like any other element. The more interesting option: put a <style> block inside the SVG file itself. A self-contained animated SVG plays everywhere SVGs render — including inside a plain <img> tag, as a CSS background, even in Markdown docs.

Code
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <style>
    @keyframes fade-in {
      from { opacity: 0; transform: scale(0.8); }
      to   { opacity: 1; transform: scale(1); }
    }
    .icon-body {
      animation: fade-in 500ms ease-out forwards;
      transform-origin: center;
      transform-box: fill-box;
    }
  </style>
  <g class="icon-body">
    <path d="M12 2L2 22h20L12 2z" />
  </g>
</svg>

Save that as a .svg file, open it in a browser, and it animates. No JavaScript was involved at any point.

The Classic "Draw" Effect

The signature SVG animation — a path drawing itself — is a trick with two stroke properties. stroke-dasharray turns the stroke into dashes; if the dash length equals the path length, you get one dash covering the entire path. stroke-dashoffset slides that dash along the path. Animate the offset from "fully off" to zero, and the path appears to draw itself.

Code
@keyframes draw {
  from { stroke-dashoffset: 100; }
  to   { stroke-dashoffset: 0; }
}

.draw-me {
  stroke-dasharray: 100;   /* >= path length */
  animation: draw 1.2s ease-in-out forwards;
}

Pro Tip

You can get the exact path length once with element.getTotalLength() in the browser console — or just overshoot. Setting dasharray larger than the path length still works; only the timing curve gets slightly less precise.

Looping Animations: Pulse and Spin

Code
@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.15); }
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.pulsing { animation: pulse 2s ease-in-out infinite; }
.spinning { animation: spin 1s linear infinite; }

Warning

The number one SVG animation gotcha: transform-origin. By default, SVG elements rotate and scale around the SVG canvas origin (top-left), not their own center — so your "spin" orbits off-screen instead of rotating in place. Fix it with transform-origin: center plus transform-box: fill-box on the animated element.

Hover-Triggered Playback

Because the animation is CSS, interactivity is just selectors. The cleanest pattern keeps the animation defined but paused, and lets hover resume it:

Code
.icon .wiggle {
  animation: wiggle 0.6s ease-in-out infinite;
  animation-play-state: paused;
}
.icon:hover .wiggle {
  animation-play-state: running;
}

Always: Respect Reduced Motion

Some users enable "reduce motion" at the OS level — for comfort, for vestibular disorders, or simply by preference. Honoring it in CSS is one media query, and there is no excuse to skip it:

Code
@media (prefers-reduced-motion: reduce) {
  .icon-body, .draw-me, .pulsing, .spinning {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}

When You Don't Want to Hand-Write This

Everything above is genuinely all you need for hand-rolled icon animation. If you are producing icons at volume, the Icora Studio bakes these same patterns — entrance, attention, looping, and exit presets, with stagger and easing controls — directly into exported SVGs, each with the reduced-motion query included automatically. And if you ever need the static version back, animations strip cleanly with one click. For the philosophical case for CSS-in-SVG over animation runtimes, see our piece on why SVG animations will outlive Lottie.

Generate an icon, pick an animation preset, and export a self-contained animated SVG at icora.io/create — then open it in a text editor to see exactly these patterns inside.

Try Icora Free

Frequently Asked Questions

Can you animate SVG with CSS alone?

Yes. SVG shapes are DOM elements, so CSS keyframes, transitions, and hover selectors work directly on them — no JavaScript or animation library required.

How do I make an SVG path draw itself?

Set stroke-dasharray to at least the path's length, then animate stroke-dashoffset from that value to zero. The single visible dash slides along the path, creating the drawing effect.

Do CSS animations work when the SVG is used in an img tag?

Yes — if the style block lives inside the SVG file itself. Styles from the surrounding page cannot reach into an img, so self-contained animated SVGs are the portable option.

Do animated SVG icons hurt performance?

Animating transform and opacity is GPU-friendly and cheap. Avoid animating properties that trigger layout, keep looping animations few, and always include a prefers-reduced-motion query.

Tags:animate SVG with CSSSVG animation tutorialCSS icon animationanimated SVG iconsstroke-dashoffset draw effect

Found this helpful? Share it!

Ready to Create Stunning Icons?

Put these principles into practice with Icora's AI-powered icon generator, professional studio tools, and developer-ready export.

Start Creating Free