How to Animate SVG Icons Step by Step
SVG icons are the perfect candidate for CSS animation — they are resolution-independent, tiny in file size, and every shape inside them is individually targetable with CSS selectors. This guide walks through the four most useful icon animation patterns, with copy-paste code for each.
Why Animate SVG Icons Specifically?
Unlike raster icons (PNG, WebP), SVG icons expose their internal structure to CSS and JavaScript. A three-bar hamburger menu, for example, is just three <line> or <rect> elements — each of which you can rotate, translate, or fade independently.
This makes it trivial to animate common UI state transitions — hamburger to X, plus to minus, play to pause, loading spinner — entirely in CSS with no JavaScript and no external library.
Pattern 1: Rotating Spinner
The simplest animated SVG icon is a loading spinner. A circle with a partial stroke gap rotated continuously creates the classic indeterminate spinner used across every design system.
<!-- SVG markup -->
<svg viewBox="0 0 24 24" width="40" height="40">
<circle
class="spinner-track"
cx="12" cy="12" r="10"
fill="none"
stroke="#2A2A2A"
stroke-width="2"
/>
<circle
class="spinner-head"
cx="12" cy="12" r="10"
fill="none"
stroke="#6366f1"
stroke-width="2"
stroke-linecap="round"
stroke-dasharray="16 47"
/>
</svg>/* CSS */
.spinner-head {
transform-origin: 50% 50%;
animation: spin 900ms linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}The stroke-dasharray creates the gap — 16px of visible stroke, 47px gap (roughly the remaining circumference of a circle with r=10).
Pattern 2: Draw-On Stroke Effect
The draw-on effect makes an SVG path appear to be drawn in real time. It works by setting stroke-dasharray to the total path length and animating stroke-dashoffset from that value down to zero.
How to get path length
In DevTools: document.querySelector("path").getTotalLength() — paste the result into your CSS.
<!-- SVG — a checkmark path -->
<svg viewBox="0 0 24 24" width="40" height="40">
<path
class="checkmark"
d="M4 13 L9 18 L20 7"
fill="none"
stroke="#6366f1"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>/* CSS */
.checkmark {
stroke-dasharray: 22; /* getTotalLength() result */
stroke-dashoffset: 22; /* start hidden */
animation: draw 600ms ease forwards;
}
@keyframes draw {
to { stroke-dashoffset: 0; }
}Pattern 3: Hover State Transition
CSS transitions on SVG properties work exactly like on HTML elements. You can animate fill, stroke, opacity, and transforms on hover with a single transition declaration.
<button class="icon-btn">
<svg viewBox="0 0 24 24" width="24" height="24">
<path class="icon-path" d="M12 2L2 7l10 5 10-5-10-5z"/>
<path class="icon-path" d="M2 17l10 5 10-5"/>
<path class="icon-path" d="M2 12l10 5 10-5"/>
</svg>
</button>/* CSS */
.icon-path {
fill: none;
stroke: #A0A0A0;
stroke-width: 2;
stroke-linecap: round;
transition: stroke 200ms ease, transform 200ms ease;
transform-origin: 50% 50%;
}
.icon-btn:hover .icon-path {
stroke: #6366f1;
transform: scale(1.1);
}Pattern 4: Hamburger → X Toggle
The hamburger-to-close animation is the most common SVG icon state transition in UI. The trick is rotating the outer bars and fading the middle one.
<svg class="hamburger" viewBox="0 0 24 24" width="32" height="32"> <line class="bar top" x1="3" y1="6" x2="21" y2="6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/> <line class="bar middle" x1="3" y1="12" x2="21" y2="12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/> <line class="bar bottom" x1="3" y1="18" x2="21" y2="18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/> </svg>
/* CSS */
.bar {
transition: transform 300ms ease, opacity 200ms ease;
transform-origin: 12px 12px; /* center of 24x24 viewBox */
}
/* open state — add .is-open to the <svg> via JS */
.hamburger.is-open .bar.top { transform: rotate(45deg) translateY(6px); }
.hamburger.is-open .bar.middle { opacity: 0; transform: scaleX(0); }
.hamburger.is-open .bar.bottom { transform: rotate(-45deg) translateY(-6px); }Toggle the .is-open class with one line of JavaScript: el.classList.toggle('is-open')
Using CSSVG to Animate Icons Visually
Writing keyframe offsets and transform values by hand gets tedious quickly. CSSVG gives you a visual timeline so you can set keyframes by scrubbing and let the tool output the exact CSS — including easing curves.
- 1Import your SVG icon via File → Import SVG. Each sub-path or shape becomes its own animatable layer.
- 2Select a layer, drag the playhead to a time, and adjust transform / opacity / fill in the Inspector panel. A keyframe is recorded.
- 3Repeat for as many keyframes as needed. The canvas previews the animation live.
- 4Export → CSS to get a self-contained SVG + CSS file. Export → SMIL for a fully standalone animated SVG that works in img tags and emails.
Common Gotchas
transform-origin on SVG elements
In SVG, transform-origin is relative to the SVG coordinate system by default, not the element's bounding box. Always set transform-box: fill-box alongside transform-origin to get intuitive center-based rotation.
Inline SVG vs <img> tag
CSS animations only work on inline SVG — SVG loaded via <img src> is sandboxed. Use inline SVG or the SMIL export (which bakes animations into the file itself).
stroke-dashoffset direction
Positive dashoffset shifts the stroke forward (revealing it from the start). Negative shifts it backward. For a left-to-right draw, animate from pathLength → 0.
Animate Your SVG Icons Visually
Skip the hand-coding. Import your icon, set keyframes visually, and export clean CSS in seconds — free, no sign-up.
Open the Editor — it's free