Published on 11/30/2025
Tags: svg
Lesson 10: CSS Transitions
Transitions are the simplest way to animate SVGs. Define a start state and an end state, and CSS smoothly interpolates between them.
Basic Transition Syntax
element {
property: startValue;
transition: property duration timing-function delay;
}
element:hover {
property: endValue;
}
Example with a circle:
<svg width="200" height="200">
<circle cx="100" cy="100" r="40" class="pulse" />
</svg>
.pulse {
fill: steelblue;
transition: fill 0.3s ease;
}
.pulse:hover {
fill: coral;
}
Hover over the circle, and it smoothly changes from blue to coral.
Transition Properties
transition-property
Which CSS property to animate:
.circle {
transition-property: fill; /* Just fill */
transition-property: fill, stroke; /* Multiple */
transition-property: all; /* Everything */
}
transition-duration
How long the animation takes:
.circle {
transition-duration: 0.3s; /* 300 milliseconds */
transition-duration: 500ms; /* Same thing */
transition-duration: 2s; /* 2 seconds */
}
transition-timing-function
The acceleration curve:
| Value | Effect |
|---|---|
ease | Slow start, fast middle, slow end (default) |
linear | Constant speed |
ease-in | Slow start |
ease-out | Slow end |
ease-in-out | Slow start and end |
cubic-bezier(...) | Custom curve |
.circle {
transition-timing-function: ease-out;
}
transition-delay
Wait before starting:
.circle {
transition-delay: 0.1s; /* Wait 100ms, then animate */
}
Shorthand
Combine all properties:
.circle {
transition: fill 0.3s ease-out 0.1s;
/* property | duration | timing | delay */
}
What Can You Transition?
✅ Works Great
fillandstroke(colors)opacitytransform(CSS transforms)stroke-widthstroke-dashoffset(for line drawing effects)
⚠️ Partially Works
stroke-dasharray(can be glitchy)
❌ Doesn’t Work
- Geometric attributes:
cx,cy,r,x,y,width,height - The
dattribute (path data) - SVG-specific
transformattribute
This is a key limitation. You can’t smoothly transition a circle’s radius with CSS — you’d need to use transform: scale() instead.
Transitioning Fill and Stroke
<svg width="200" height="200">
<rect x="50" y="50" width="100" height="100" class="box" />
</svg>
.box {
fill: #3b82f6;
stroke: #1d4ed8;
stroke-width: 2;
transition: fill 0.2s, stroke 0.2s, stroke-width 0.2s;
}
.box:hover {
fill: #ef4444;
stroke: #b91c1c;
stroke-width: 4;
}
Transitioning Transforms
This is where CSS transitions really shine for SVG:
<svg width="200" height="200">
<rect x="60" y="60" width="80" height="80" class="spin-box" />
</svg>
.spin-box {
fill: mediumseagreen;
transform-origin: center;
transform: rotate(0deg) scale(1);
transition: transform 0.4s ease-out;
}
.spin-box:hover {
transform: rotate(180deg) scale(1.1);
}
Note: transform-origin: center is crucial! Without it, the rotation happens around (0, 0).
Transitioning Opacity
Perfect for fade effects:
<svg width="200" height="200">
<circle cx="100" cy="100" r="60" fill="coral" class="fade" />
<text x="100" y="105" text-anchor="middle" class="label">Hover me</text>
</svg>
.label {
opacity: 0;
transition: opacity 0.3s;
}
svg:hover .label {
opacity: 1;
}
Staggered Transitions
Add delays to create sequential animations:
<svg width="200" height="100">
<circle cx="40" cy="50" r="15" class="dot dot-1" />
<circle cx="80" cy="50" r="15" class="dot dot-2" />
<circle cx="120" cy="50" r="15" class="dot dot-3" />
<circle cx="160" cy="50" r="15" class="dot dot-4" />
</svg>
.dot {
fill: steelblue;
transform-origin: center;
transform: scale(1);
transition: transform 0.2s ease-out;
}
svg:hover .dot {
transform: scale(1.3);
}
.dot-1 {
transition-delay: 0s;
}
.dot-2 {
transition-delay: 0.05s;
}
.dot-3 {
transition-delay: 0.1s;
}
.dot-4 {
transition-delay: 0.15s;
}
When you hover the SVG, the dots scale up one after another.
Transitioning stroke-dashoffset (Line Drawing)
This technique creates the “drawing” effect:
<svg width="200" height="200">
<path d="M 20 100 Q 100 20, 180 100"
class="draw-line"
fill="none"
stroke="white"
stroke-width="3" />
</svg>
.draw-line {
stroke-dasharray: 200; /* Total length of path */
stroke-dashoffset: 200; /* Hide all of it */
transition: stroke-dashoffset 1s ease-out;
}
svg:hover .draw-line {
stroke-dashoffset: 0; /* Reveal all of it */
}
The line appears to draw itself on hover. We’ll cover this technique in depth in Lesson 15.
Tap or hover to see the animation...
Using CSS Variables for Dynamic Transitions
.icon {
--icon-color: #64748b;
--icon-scale: 1;
fill: var(--icon-color);
transform: scale(var(--icon-scale));
transform-origin: center;
transition: fill 0.2s, transform 0.2s;
}
.icon:hover {
--icon-color: #3b82f6;
--icon-scale: 1.1;
}
This makes it easy to theme and adjust transitions.
Multiple Elements, One Hover
Trigger transitions on children when parent is hovered:
<svg width="200" height="200" class="icon-container">
<circle cx="100" cy="100" r="70" class="bg" />
<path d="M 70 100 L 90 120 L 130 80" class="check" />
</svg>
.bg {
fill: #e2e8f0;
transition: fill 0.3s;
}
.check {
stroke: #64748b;
stroke-width: 8;
stroke-linecap: round;
stroke-linejoin: round;
fill: none;
transition: stroke 0.3s;
}
.icon-container:hover .bg {
fill: #22c55e;
}
.icon-container:hover .check {
stroke: white;
}
Practical Example: Button Icon
<button class="btn">
<svg width="24" height="24" viewBox="0 0 24 24" class="arrow">
<path d="M 5 12 H 19 M 12 5 L 19 12 L 12 19"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
fill="none" />
</svg>
Next
</button>
.btn {
display: flex;
align-items: center;
gap: 0.5rem;
color: white;
}
.arrow {
transition: transform 0.2s ease-out;
}
.btn:hover .arrow {
transform: translateX(4px);
}
The arrow slides right on hover.
Exercise 10.1: Color Transition
Create a rectangle that transitions from steelblue to coral fill, and from navy to darkred stroke on hover.
Exercise 10.2: Scale on Hover
Create three circles. On hover, they should:
- Scale up by 20%
- Change fill color
- Stagger the animation (0ms, 100ms, 200ms delay)
Exercise 10.3: Icon Reveal
Create an icon with two parts:
- A background circle
- A symbol (plus sign, check, arrow, etc.)
On hover:
- Background changes color
- Symbol fades in from opacity 0
Key Takeaways
transitionsmoothly animates between states- Works with: fill, stroke, opacity, transform
- Doesn’t work with: geometric attributes (cx, r, d, etc.)
- Use
transform-origin: centerfor intuitive rotations and scales - Use
transition-delayfor staggered effects - Combine with
:hoverfor interactive animations