SVG Morph Animation Reference

Tiger AbrodiTiger Abrodi
4 min read

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

  1. Identify start/end shapes

  2. Choose ONE element type that can represent both

  3. Find attributes that change between the shapes

  4. 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 TypeBest ElementAnimate
Circle ↔ Rectangle<rect>rx attribute
Simple shapes<polygon>points attribute
Complex curves<path>d attribute
Size changesAny elementwidth, height, r, etc.

CSS vs SMIL Animation

<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!

0
Subscribe to my newsletter

Read articles from Tiger Abrodi directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Tiger Abrodi
Tiger Abrodi

Just a guy who loves to write code and watch anime.