How SVG Shape Morphing Works

Avatar of Chris Coyier
Chris Coyier on (Updated on )

While animating SVG with CSS is easy and comfortable, CSS can’t animate all the SVG properties that are possible to animate. For instance, all the properties that define the actual shape of the elements aren’t possible to change or animate in CSS. You can animate them through SMIL though. Sara Soueidan covers this in her guide to SMIL here on CSS-Tricks, but I thought I would shine a light on this particular ability.

Update: This post is all about SVG shape morphing with SMIL. SMIL has an uncertain (likely not good) future. If you’re super interested in shape morphing (which you should be, it’s awesome!) I recommend checking out GreenSock’s MorphSVG plugin, which doesn’t require SMIL and is far more powerful as it can morph between shapes regardless of number of points, type of element, and cross-browser.
Another update: Chrome has started to allow shape morphing through CSS. Here’s a Pen that demonstrates that. It’s even more limiting than SMIL though, being limited to the one browser and requiring a path with an identical number of points. Also not hardware accelerated, like all SVG.

Most important fact: the shapes need to have the same number of points

Otherwise, the animation will just fail. The shape won’t disappear or anything, but it won’t animate.

It’s not extremely obvious how many points a shape has just by looking at the d (in the case of a path) or points attribute (in the case of a polygon) so you may just need to start in a vector editor program with a single shape and work from there.

1. Start with the most complicated shape

In this demo I’m going to morph from a star to a check. The star is more complex:

Save a copy of that SVG, then make a new copy for the next shape.

2. Make the next shape with those same points.

Drag the points around until you have your next shape.

3. Use the starting shape on the SVG shape element itself

<svg viewBox="0 0 194.6 185.1">

  <polygon fill="#FFD41D" points=" ... shape 1 points ... ">

  </polygon>

</svg>

4. Add an animation element that animates to the next shape

<svg viewBox="0 0 194.6 185.1">

  <polygon fill="#FFD41D" points=" ... shape 1 points ... ">

    <animate attributeName="points" dur="500ms" to=" ... shape 2 points ... " />

  </polygon>

</svg>

That animation will run immediately, so we’ll need to fix that up a bit.

5. Trigger the animations as needed

SMIL has the ability to handle interactions like clicks and hovers, so long as all that happens within the SVG itself. For instance, you could begin the animation when it’s clicked on, like:

<polygon id="shape" points=" ... shape 1 points ... ">

  <animate begin="shape.click" attributeName="points" dur="500ms" to=" ... shape 2 points ... />

</polygon>

That’s pretty neat, but it’s a little limiting since you can only handle clicks from other elements right in that same SVG. Perhaps this SVG is just a part of a <button> and you want to run the animation on any click on that button.

First give the animation an ID so we can find it with JavaScript, and then prevent it from running with:

<animate id="animation-to-check" begin="indefinite" ... />

Now you can get a reference to that animation and kick if off how you like:

animationToCheck = document.getElementById("animation-to-check");

// run this on a click or whenever you want
animationToCheck.beginElement();

Demo

This demo actually has four animations. One to morph the star to a check, one to change the color, and then both those same animations in reverse. Clicking the button checks the state of the button and then runs the appropriate ones.

See the Pen Shape Morph Button by Chris Coyier (@chriscoyier) on CodePen.

Would be pretty cool for charts, like this old Raphael demo: