CSS is very good at moving elements “point-to-point” using keyframe animation, or making objects scale, arc, or swing. It can even recreate traditional “pose-to-pose” animation using step()
. But CSS usually comes up against hard limits when trying to move elements along a curved or complex path.
Derived from technology that has been in SVG for a decade, the new Motion Path specification allows elements to follow curving, pre-plotted paths in native HTML and CSS, with some assistance from SVG. At the time of writing, CSS motion path is only supported in Chrome 46+, Opera 33+, and the latest version of the Android browser.
Go Ask Alice
Let’s start with the example at the top of this page. Alice is just a straightforward PNG image: the tricky part is the path. I’ve found the best results by creating paths with the following steps:
- Create your path in Adobe Illustrator or another vector editing program. The path for the above animation looks like this:
And the code, something like this:
<svg xmlns="http://www.w3.org/2000/svg" width="388px" height="401.1px" viewBox="0 0 388 401.1"> <path fill="#FFF" stroke="#000" d="M69.8, 98.3c116.9, 0,76.9, 261.5, 261.5, 261.5 s103.8-195.4, 233.8-195.4S627.5, 356, 715.2, 356"/> </svg>
- Remove all of the SVG code except for the path information; that is, keep the value following the
d
attribute, and eliminate the rest. - Ensure that path coordinates have spaces after each of the commas, and no carriage returns in the path coordinate sequence (while it shouldn’t make any difference, I’ve found Chrome to have problems interpreting motion paths with either).
- Reference the code inside the CSS for the element to be moved, as the value of a
motion-path
property:#alice { motion-path: path("M69.8, 98.3c116.9, 0,76.9, 261.5, 261.5, 261.5 s103.8-195.4, 233.8-195.4S627.5, 356, 715.2, 356"); }
- Create an animation for the element, using the new
motion-offset
property:@keyframes rabbithole { 0% { motion-offset: 0; } 100% { motion-offset: 100%; } }
In Alice’s case, I’m also scaling her as the animation proceeds:
@keyframes rabbithole { 0% { motion-offset: 0; transform: scale(1); } 100% { motion-offset: 100%; transform: scale(0); } }
- Finally, call on the animation:
#alice { animation: rabbithole 2.2s forwards; }
On-Point
By default, the animated element is auto-aligned to the tangent of the motion path. This behaviour can be manipulated with the motion-rotation
property: setting the new property to a value of reverse
will mirror the element (making it animate through the path facing “backwards”), while providing an angle (for example, motion-rotation: -45deg
) will force the element to follow the path in a fixed orientation.
It’s also important to note that the element will be animated from the first drawn point in the SVG, although this default behaviour can be changed by using reversed values for motion-offset
.
Conclusion
Motion Path is the most exciting addition to CSS animation in the last five years, and this introductory article barely scratches the surface of its possibilities. What’s holding it back from general use is lack of broad browser support; however, given the specification’s similarities to the original SVG implementation, it shouldn’t to too difficult to create a polyfill for browsers to duplicate a motion path in SVG. If I ever complete work on my machine that stops time, that will be one of the first things I’ll turn to; for now, I’ll follow up this article with another covering the SVG equivalent, so those interested can use the same concepts in that technology for their web pages.
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/wKryMy