An illustration of Lewis Caroll's Alice with her hand raised

This article is also available in French and Spanish

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 has traditionally come 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+ and Opera 33; in order to see the demos you’ll need to ensure that your browser is updated to the latest version. (I discuss alternatives and future adoptions at the end of this article).

Go Ask Alice

Let’s start with the example at the top of this page. Alice is just a straightforward PNG: the tricky part is the path. I’ve found the best results by creating paths with the following steps:

  1. 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>
  2. Remove all of the SVG code except for the path information; that is, keep the value following the d attribute, and eliminate the rest.
  3. 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 that Chrome currently has problems interpreting motion paths with either).
  4. 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");
    }
  5. 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); }
    }
  6. Finally, call on the animation:
    #alice {
        will-change: transform;
        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.