SVG Morph Animation Reference

Core Principle
Morph = animate attributes of the SAME element, not between different elements
<!-- ❌ Wrong: Different elements -->
<circle r="25" />
<rect width="50" height="50" />
<!-- ✅ Right: Same element, animate attributes -->
<rect width="50" height="50" rx="25">
<animate attributeName="rx" to="0" dur="1s" />
</rect>
The Process
Identify start/end shapes
Choose ONE element type that can represent both
Find attributes that change between the shapes
Animate those attributes
Common Morph Patterns
Circle ↔ Rectangle
Use <rect> with rx attribute
<!-- Circle: rx = half of width/height -->
<rect x="25" y="25" width="50" height="50" rx="25" />
<!-- Rectangle: rx = 0 -->
<rect x="25" y="25" width="50" height="50" rx="0" />
<!-- Animation -->
<rect x="25" y="25" width="50" height="50" rx="25">
<animate attributeName="rx" to="0" dur="1s" />
</rect>
Line ↔ Triangle
Use <polygon> with same point count
<!-- Triangle: 3 distinct points -->
<polygon points="12 4, 20 16, 4 16" />
<!-- Line: collapse top point to baseline -->
<polygon points="12 16, 20 16, 4 16" />
<!-- Animation -->
<polygon points="12 16, 20 16, 4 16">
<animate attributeName="points" to="12 4, 20 16, 4 16" dur="1s" />
</polygon>
Rectangle ↔ Triangle
Use <polygon> with 4 points (overlap for triangle)
<!-- Rectangle: 4 corners -->
<polygon points="0 0, 24 0, 24 24, 0 24" />
<!-- Triangle: move one point to overlap another -->
<polygon points="0 0, 24 24, 24 24, 0 24" />
<!-- Animation -->
<polygon points="0 0, 24 0, 24 24, 0 24">
<animate attributeName="points" to="0 0, 24 24, 24 24, 0 24" dur="1s" />
</polygon>
Point Count Rule
CRITICAL: Same number of points in start and end states
<!-- ❌ Breaks: 4 points → 3 points -->
<animate
attributeName="points"
from="0 0, 24 0, 24 24, 0 24"
to="0 0, 24 24, 0 24"
/>
<!-- ✅ Works: 4 points → 4 points -->
<animate
attributeName="points"
from="0 0, 24 0, 24 24, 0 24"
to="0 0, 24 24, 24 24, 0 24"
/>
Solution: Overlap points
Want 3 points? Make 2 points share same coordinates
"12 4, 20 16, 20 16, 4 16"= triangle with 4 points
Path Morphing
Use <path> with same command structure
<!-- Both paths need same commands -->
<path d="M10 10 L50 10 L50 50 L10 50 Z">
<animate attributeName="d" to="M10 10 L30 30 L50 50 L10 50 Z" dur="1s" />
</path>
Element Choice Guide
| Morph Type | Best Element | Animate |
| Circle ↔ Rectangle | <rect> | rx attribute |
| Simple shapes | <polygon> | points attribute |
| Complex curves | <path> | d attribute |
| Size changes | Any element | width, height, r, etc. |
CSS vs SMIL Animation
SMIL (recommended for morphing)
<rect rx="25">
<animate attributeName="rx" to="0" dur="1s" fill="freeze" />
</rect>
CSS (limited support for morphing)
/* Only works for simple numeric attributes */
rect {
rx: 25;
transition: rx 1s;
}
rect:hover {
rx: 0;
}
Common Gotchas
Coordinate System
<!-- Coordinates must fit viewBox -->
<svg viewBox="0 0 24 24">
<polygon points="12 4, 20 16, 4 16" />
<!-- ✅ Fits -->
<polygon points="120 40, 200 160, 40 160" />
<!-- ❌ Outside viewBox -->
</svg>
Point Order Matters
<!-- Points animate in order: 1→1, 2→2, 3→3, 4→4 -->
<animate
attributeName="points"
from="0 0, 24 0, 24 24, 0 24"
to="12 0, 24 12, 12 24, 0 12"
/>
Path Command Compatibility
<!-- ❌ Different commands don't morph smoothly -->
<animate attributeName="d" from="M10 10 L50 50" to="M10 10 Q30 20 50 50" />
<!-- ✅ Same commands work better -->
<animate
attributeName="d"
from="M10 10 Q30 30 50 50"
to="M10 10 Q30 20 50 50"
/>
Practical Examples
Button State Changes
<rect rx="0" class="button-bg">
<animate attributeName="rx" to="8" dur="0.3s" begin="button.mouseenter" />
<animate attributeName="rx" to="0" dur="0.3s" begin="button.mouseleave" />
</rect>
Icon Transformations
<!-- Play button → Pause button -->
<polygon points="8 5, 8 19, 19 12">
<animate attributeName="points" to="8 5, 10 5, 10 19, 8 19" dur="0.3s" />
</polygon>
Loading States
<circle r="5">
<animate attributeName="r" values="5;8;5" dur="1s" repeatCount="indefinite" />
</circle>
Quick Reference
<!-- Circle to square -->
<rect rx="25"><animate attributeName="rx" to="0" /></rect>
<!-- Line to triangle -->
<polygon points="12 16, 20 16, 4 16">
<animate attributeName="points" to="12 4, 20 16, 4 16" />
</polygon>
<!-- Complex path morph -->
<path d="start-path">
<animate attributeName="d" to="end-path" />
</path>
Remember: You're not changing shapes, you're moving points!






