How to Animate SVG in CSS
From simple fade-ins to stroke draw effects — learn how to bring SVG illustrations to life with pure CSS animations, no JavaScript required.
CSS animations work beautifully with SVG. Because SVG elements are just DOM elements, you can apply the same @keyframes animations you'd use on any HTML element — but with far more control over individual shapes, paths and colors within the illustration.
The basics: how CSS animation works on SVG
To animate an SVG, you either:
- Add a CSS class to the
<svg>element and animate the whole illustration, or - Target individual child elements (
path,circle,rect, etc.) for more granular effects
One important quirk: for transform-based animations (rotate, scale, translate) to work correctly in SVG, you need to set these two CSS properties:
.my-svg {
transform-origin: 50% 50%;
transform-box: fill-box;
}
transform-box: fill-box makes the transform origin relative to the element's own bounding box rather than the viewport — without this, rotations and scales often behave unexpectedly.
1. Fade In
The simplest animation. Great for hero illustrations that appear as the page loads.
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.illustration {
animation: fadeIn 0.8s ease-in-out forwards;
}
2. Float
A gentle up-and-down motion. Perfect for hero illustrations, empty-state graphics, or product mockups.
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-14px); }
}
.illustration {
animation: float 3s ease-in-out infinite;
}
3. Bounce
Drops in from above and bounces to a rest position. Good for success states or confirmation screens.
@keyframes bounce {
0% { transform: translateY(30px); opacity: 0; }
60% { transform: translateY(-8px); opacity: 1; }
80% { transform: translateY(4px); }
100% { transform: translateY(0); opacity: 1; }
}
.illustration {
animation: bounce 0.7s cubic-bezier(0.36, 0.07, 0.19, 0.97) forwards;
}
4. Pulse
Gently scales the illustration up and down. Works well for attention-grabbing CTAs or notification indicators.
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.08); }
}
.illustration {
transform-origin: 50% 50%;
transform-box: fill-box;
animation: pulse 2s ease-in-out infinite;
}
5. Spin
Continuous rotation around the Z axis. Use sparingly — good for loading indicators or icon badges.
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.illustration {
transform-origin: 50% 50%;
transform-box: fill-box;
animation: spin 2s linear infinite;
}
6. Stroke Draw Effect
This is the most impressive CSS SVG technique — it makes paths appear to draw themselves. It relies on the stroke-dasharray and stroke-dashoffset properties.
How it works
SVG strokes can be rendered as dashes. stroke-dasharray sets the length of each dash; stroke-dashoffset shifts where the dash pattern starts. By setting both to the total path length, the stroke is invisible. Animating stroke-dashoffset to 0 makes it appear to draw in from the start of the path.
/* Step 1: Measure the path length in JS */
const path = document.querySelector('.my-path');
const length = path.getTotalLength();
/* Step 2: Set initial state */
path.style.strokeDasharray = length;
path.style.strokeDashoffset = length;
/* Step 3: Trigger the animation */
path.style.animation = 'draw 2s ease-in-out forwards';
@keyframes draw {
to { stroke-dashoffset: 0; }
}
Staggering multiple paths
For an illustration with many paths, stagger the animation delay so each path draws in sequence:
const paths = document.querySelectorAll('path');
const totalDuration = 2; // seconds
paths.forEach((path, i) => {
const length = path.getTotalLength();
const delay = (i / paths.length) * totalDuration * 0.75;
path.style.strokeDasharray = length;
path.style.strokeDashoffset = length;
path.style.animation = `draw 1s ease-in-out ${delay}s forwards`;
});
Applying animations only to specific elements within an SVG
You can target individual elements inside an SVG by giving them an id or class:
<svg>
<circle id="planet" cx="200" cy="200" r="80" fill="#586EFF"/>
<path class="orbit-ring" d="M 50 200 A 150 150 0 1 1 350 200"/>
</svg>
#planet {
transform-origin: 50% 50%;
transform-box: fill-box;
animation: pulse 3s ease-in-out infinite;
}
.orbit-ring {
animation: draw 2s ease-in-out forwards;
}
Respecting user preferences
Always wrap motion animations in a prefers-reduced-motion media query. Some users experience motion sickness from animations, and it's a simple accessibility fix:
@media (prefers-reduced-motion: reduce) {
.illustration {
animation: none;
}
}
Animate any SVG illustration
Upload an SVG, choose an animation style, preview it live, and download the animated file — all in your browser.
Try the SVG Animation tool →