What Is CSS Animation and How Do You Use It?
CSS animation is a way to change an element's style over time using @keyframes and animation properties, without JavaScript. Use it when you need multi-step motion, looping, or staggered sequences; use a CSS transition instead when you only need a simple A-to-B change triggered by a state like :hover or a class toggle.
CSS Animation vs. Transition
Both animate CSS properties, but they solve different problems.
| Transition | Animation | |
|---|---|---|
| Trigger | A property change (hover, class, focus) | Runs on its own once applied |
| Steps | Two states (start → end) | Any number of keyframe steps |
| Looping | No | Yes, via animation-iteration-count |
| Direction control | No | Yes, via animation-direction |
| Typical use | Button hover, menu open | Loading spinners, drawing effects, entrance sequences |
Rule of thumb: if the change is "when X happens, go from A to B," use a transition. If it's "play this sequence," use an animation.
The Core Pieces
A CSS animation has two parts: the keyframes that define what happens, and the properties that control how it plays.
@keyframes draw {
from { stroke-dashoffset: 1000; }
to { stroke-dashoffset: 0; }
}
.line {
stroke-dasharray: 1000;
animation-name: draw;
animation-duration: 2s;
animation-timing-function: ease-in-out;
animation-delay: 0.3s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
}
The shorthand form is animation: draw 2s ease-in-out 0.3s 1 normal forwards;.
Key properties and what they do:
animation-name— which@keyframesblock to run.animation-duration— how long one cycle takes. Without a duration (or with0s), nothing visibly happens.animation-timing-function— the easing curve:linear,ease,ease-in,ease-out,ease-in-out, plus thecubic-bezier()andsteps()functions.animation-delay— wait time before the animation starts.animation-iteration-count— how many times it repeats;infiniteloops forever.animation-direction—normal,reverse,alternate, oralternate-reverse.animation-fill-mode— what styles apply before and after:forwardskeeps the end state,backwardsapplies the start state during the delay,bothdoes both.animation-play-state—runningorpaused, useful for pausing on hover.
Animating SVG Stroke and Fill for a Drawing Effect
The classic "self-drawing" SVG effect animates two stroke properties: stroke-dasharray and stroke-dashoffset. stroke-dasharray sets the dash pattern along the path, and stroke-dashoffset shifts where that pattern starts. Set the dash length to at least the path length, then animate the offset from that length down to 0 so the stroke appears to draw itself.
@keyframes draw {
to { stroke-dashoffset: 0; }
}
.svg-elem-1 {
stroke-dasharray: 1200;
stroke-dashoffset: 1200;
animation: draw 2s ease-in-out forwards;
}
Fill animations work the same way conceptually but animate fill (often fill-opacity or a color) instead of stroke properties, so a shape can fade or fill in after its outline is drawn.
Tools like SVG Artista generate this CSS for you: you paste SVG markup, choose an animation type (transition, stroke, or fill), set duration, stagger step, delay, easing, and direction, then copy the generated code. The easing options it exposes — linear, ease, easeIn, easeOut, easeInOut, and the quadratic/cubic/quart/quint/sine/expo/circ/back variants — map directly to the timing functions above, and its "stagger step" is what produces the sequenced, one-path-after-another look.
Staggering and Sequencing Multiple Elements
To make several elements animate in order rather than all at once, give each one an increasing animation-delay. If each element should take the same time, keep animation-duration identical and only shift the delay.
.svg-elem-1 { animation-delay: 0s; }
.svg-elem-2 { animation-delay: 0.2s; }
.svg-elem-3 { animation-delay: 0.4s; }
A "stagger step" is just this increment. If you have many elements, generate the delays with a loop in your build step or a CSS custom property rather than writing each rule by hand.
Common Problems
- Animation doesn't run. Usually a missing
animation-duration, a@keyframesname that doesn't matchanimation-name, or the element beingdisplay: none. - It jumps back at the end. Add
animation-fill-mode: forwardsso the final keyframe state persists. - SVG path draws too fast or not at all. The
stroke-dasharrayvalue is likely smaller than the actual path length, so the whole line is already visible. Measure the path length and set the dash value to match or exceed it. - Vendor prefixes. Older browsers needed
-webkit-prefixes for@keyframesand animation properties. Modern browsers support the unprefixed versions, so add prefixes only if you must support legacy targets. - Performance. Animating
transformandopacityis cheap because it can run on the compositor. Animating layout-affecting properties likewidth,height,top, orleftforces reflow each frame and can stutter. For SVG stroke drawing,stroke-dashoffsetis the standard approach and is generally smooth, but test on your target devices.
Quick Decision Guide
- Simple state change on hover or focus → transition.
- Multi-step, looping, or self-starting motion → animation.
- SVG line drawing → animate
stroke-dashoffsetwithstroke-dasharrayset to the path length. - Sequential reveal across many elements → same duration, increasing
animation-delay. - Need the end state to stick →
animation-fill-mode: forwards.