`Every time I see a developer reach for a JavaScript library just to animate an SVG icon, I die a little inside. A spinning loader? A draw-in logo? A hover effect on an illustration? You don't need GreenSock. You don't need Anime.js. You don't need a single line of JavaScript.
CSS can animate SVG directly. It's faster, lighter, and simpler than pulling in a dependency. Here's how to do it.
The Foundation: SVG and CSS Working Together
SVG elements in the DOM are just elements — which means CSS properties like transform, opacity, and custom stroke-* properties apply to them. The key difference from animating HTML elements is that SVG uses its own coordinate system for transforms (centered on the SVG viewBox, not the element's center), and it has special properties for line drawing.
Technique 1: Draw-In Effects with stroke-dasharray and stroke-dashoffset
This is the most satisfying SVG animation technique. It makes it look like an artwork is being drawn by an invisible pen.
`css
.path {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: draw 2s ease-in-out forwards;
}
@keyframes draw {
to {
stroke-dashoffset: 0;
}
}`
How it works: stroke-dasharray creates a dashed line. When the dash length equals the total path length, the line is solid. stroke-dashoffset slides that dash along the path. Start with the offset equal to the path length (the "dash" is shifted completely out of view), then animate it to 0. The line appears to draw itself.
Pro tip: You need the exact path length for this to work. Use path.getTotalLength() in your browser's DevTools console to find it, then set both stroke-dasharray and stroke-dashoffset to that value. Or just use a generously large value like 1000 — it works as long as both properties match.
Technique 2: CSS Transforms for Scaling and Rotation
SVG elements respond to transform just like HTML elements, but with one gotcha: the transform origin defaults to (0, 0) of the SVG viewBox, not the center of the element.
`.gear {
animation: spin 4s linear infinite;
transform-origin: center;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}`
For complex grouped SVGs, you may need to set transform-origin explicitly to the center of the group's bounding box. Use percentage values or specific pixel coordinates.
.gear-group {
transform-origin: 120px 120px;
}
Technique 3: Staggered Animations with animation-delay
Multiple elements animating at the same time looks mechanical. Add delays to create a cascade effect.
.logo-letter:nth-child(1) { animation-delay: 0s; }
.logo-letter:nth-child(2) { animation-delay: 0.1s; }
.logo-letter:nth-child(3) { animation-delay: 0.2s; }
.logo-letter:nth-child(4) { animation-delay: 0.3s; }
.logo-letter:nth-child(5) { animation-delay: 0.4s; }
Combine this with animation-fill-mode: backwards so elements stay invisible before their animation starts, and you get a polished reveal sequence with zero JavaScript.
Performance: CSS vs. JavaScript
For simple SVG animations (transforms, opacity, stroke-draw), CSS animations are faster than JavaScript libraries. Here's why:
CSS animations run on the compositor thread, not the main thread. JavaScript runs on the main thread. If your page is doing other work (network requests, layout calculations), JS animations hitch. CSS animations don't.
CSS animations have zero bundle cost. GreenSock is ~40KB minified. Anime.js is ~15KB. Even a few lines of custom JS requestAnimationFrame logic adds maintenance cost. CSS keyframes are free.
The GPU can accelerate CSS transform and opacity animations without involving the CPU. JS libraries can trigger GPU compositing, but they add overhead.
The one place JS wins: complex timeline sequencing, physics-based motion (springs, easing curves you can't express in CSS), and path morphing across multiple shapes. But for 90% of real-world SVG animation needs — loaders, hovers, draw-in effects, reveals — CSS is the better tool.
Real Scenario: A Loading Spinner and an Animated Logo
Loading Spinner (no JS, no images)
<svg viewBox="0 0 50 50" class="spinner">
<circle cx="25" cy="25" r="20" fill="none" stroke="#6366f1" stroke-width="4" />
</svg>
`.spinner circle {
stroke-dasharray: 126;
stroke-dashoffset: 126;
transform-origin: center;
animation: spin 1.2s linear infinite;
}
@keyframes spin {
to {
stroke-dashoffset: 0;
transform: rotate(360deg);
}
}`
One element, two properties, zero JS. Works in every modern browser.
Animated Logo Draw-In
A 5-letter wordmark where each letter draws in sequence:
`.wordmark path {
stroke-dasharray: 500;
stroke-dashoffset: 500;
animation: draw 0.8s ease-out forwards;
}
.wordmark path:nth-child(1) { animation-delay: 0s; }
.wordmark path:nth-child(2) { animation-delay: 0.15s; }
.wordmark path:nth-child(3) { animation-delay: 0.3s; }
.wordmark path:nth-child(4) { animation-delay: 0.45s; }
.wordmark path:nth-child(5) { animation-delay: 0.6s; }
@keyframes draw {
to { stroke-dashoffset: 0; }
}
The letters appear one after another, each drawing itself from left to right. Clean, performant, and entirely CSS-driven.
The Easy Way
You don't need to write all this CSS by hand for every project. I built an SVG animation playground where you can upload any SVG, experiment with draw-in, spin, fade, and stagger effects visually, and export the CSS code — no login, no uploads, no JavaScript.
I build lightweight browser-based tools at utilitylab.dev. If you want a free, no-login tool to animate SVGs with pure CSS and export the code, there's one at <https://utilitylab.dev/svg-animator>.
Top comments (0)