RedfernDev.

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:

ValueEffect
easeSlow start, fast middle, slow end (default)
linearConstant speed
ease-inSlow start
ease-outSlow end
ease-in-outSlow 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

  • fill and stroke (colors)
  • opacity
  • transform (CSS transforms)
  • stroke-width
  • stroke-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 d attribute (path data)
  • SVG-specific transform attribute

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;
}
Tap me

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

  • transition smoothly animates between states
  • Works with: fill, stroke, opacity, transform
  • Doesn’t work with: geometric attributes (cx, r, d, etc.)
  • Use transform-origin: center for intuitive rotations and scales
  • Use transition-delay for staggered effects
  • Combine with :hover for interactive animations

Next: Lesson 11: Keyframe Animations