· 4 min read
How to Animate an SVG With CSS Keyframes
Manesh Jayawardhana
CIO & Co-founder
The draw-on effect — a line that appears as if being drawn — is the most requested SVG animation and the one that most often comes out wrong. It starts half-drawn, or finishes early, or jumps at the beginning.
All three are the same bug, and it’s a number.
How the draw-on effect works
There’s no “draw” property in CSS. The effect is a trick using the dash pattern.
stroke-dasharray sets a repeating pattern of dash and gap lengths. Set it to the full length of the path and you get one dash exactly as long as the path — a solid line, looking normal.
stroke-dashoffset shifts where that pattern starts. Set it to the path length as well and the dash is pushed entirely off the end, so nothing renders.
Animate the offset from the path length down to zero, and the dash slides into view. The line appears to draw itself.
path {
stroke-dasharray: 640;
stroke-dashoffset: 640;
animation: draw 1.2s ease-out forwards;
}
@keyframes draw {
to { stroke-dashoffset: 0; }
}
The 640 is the path’s actual length in user units. That number has to be right. Too small and the animation starts part-drawn; too large and it finishes before the timeline ends, so the line sits still for the remainder.
Get it from path.getTotalLength() in the browser console rather than estimating. It takes one line and it’s the difference between a working effect and an inexplicable one.
Respecting reduced motion
Some people experience nausea, dizziness or migraine from animation. Operating systems expose a “reduce motion” setting for exactly this, and browsers surface it as a media query.
Honouring it is two lines:
@media (prefers-reduced-motion: reduce) {
path { animation: none; stroke-dashoffset: 0; }
}
The key detail is showing the end state, not hiding the element. Someone who asked for less motion still wants to see the illustration — they want it to arrive without moving.
CSS rather than SMIL
SVG has its own animation syntax, SMIL, using <animate> elements. It’s been deprecated in at least one major engine and support has been inconsistent for years.
CSS animations and transforms are well supported, easier to control from JavaScript, and integrate with the rest of your styling. For anything new, use CSS.
| Technique | Support | Use |
|---|---|---|
| CSS keyframes | Universal | Default choice |
| CSS transitions | Universal | State changes |
SMIL <animate> | Inconsistent, deprecated in places | Legacy only |
| JavaScript (WAAPI) | Good | Complex sequencing |
Common mistakes to avoid
- Estimating path length rather than measuring it.
- Animating
transformon an SVG child without settingtransform-box: fill-box, which makes the origin behave unexpectedly. - Omitting the reduced-motion guard.
- Hiding the element entirely under reduced motion, rather than showing its final state.
- Animating a path with
stroke-linecap: round, where the cap makes the length slightly longer thangetTotalLength()reports and the end looks abrupt.
How to do it with SVG Animator
The SVG Animator generates the markup and CSS with the guard included.
- Add the SVG and choose the animation type.
- Set duration and easing — draw-on effects read best between one and two seconds.
- Keep the reduced-motion guard, which is on by default.
- Paste the SVG and its CSS into your page and check the path length matches.
MDN’s guide to prefers-reduced-motion covers the media query in full. Other design tools are in the tools directory.
Frequently asked questions
Why does my draw-on animation start halfway?
Because the dasharray value doesn’t match the path’s true length. Measure it with getTotalLength() rather than estimating.
Should SVG be animated with CSS or SMIL?
CSS, for anything new. SMIL is deprecated in some engines and support is inconsistent; CSS keyframes and transforms are well supported and easier to control.
Why respect prefers-reduced-motion?
Because motion triggers nausea and vestibular symptoms for some people, and the OS preference is how they ask for less of it. Honouring it is a two-line media query.
Final thought
Measure the path, animate the offset, guard for reduced motion. Three steps, and the first one is the only one people skip.