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.
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
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.
<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();
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.
Would be pretty cool for charts, like this old Raphael demo: