Hi! 2016 was a while ago and there have been a few updates to Motion Path since then (including more browser support!)... Check out a more recent article written in early 2020 danielcwilson.com/blog/2020/01/motion-path-quirks/ for the latest.

Summer of 2015 brought wind of the first implementation of the new CSS Motion Path module (Blink-based Chrome and Opera) via three new CSS properties: motion-path, motion-offset, motion-rotation. There are several changes in 2016 after Motion Path merged with related pieces in another spec for round displays and polar coordinates.

This means a few things, the first being we no longer have these motion properties, as they have been renamed to offset. So motion-path is now offset-path, and motion-offset is now offset-distance. On the one hand the change makes sense since motion only happens when these properties are combined with CSS Animations and Transitions. Alone these properties simply place an element along the path. If you just want to place something along a path you declare one position for it with offset-distance. If you want motion along the path, then you animate the offset-distance property via CSS Animations or Transitions.

This demo uses the new syntax, so it will work in Chrome 56+ and Opera 43+. I also have a version of this demo using the old motion properties (viewable in Chrome 46+). Since Chrome and Opera are the only browsers that implemented the original spec version, if you want to play around with CSS Motion Path today I'd recommend focusing strictly on the new offset properties without worrying about fallbacks.

But this is still an early spec, so the name (and functionality) is likely to change again. This article is just capturing where the spec stands in October 2016.

The Basics

I previously wrote a post on how to use the original CSS Motion Path implementation. Let's take a quick look at how we work with the new spec, in particular as implemented in Chrome Canary 55 with the new offset properties.

offset-path

The ever important offset-path defines our path along which to place our element. You can define a path in a fashion similar to how it is defined in SVG 1.1:

  offset-path: path("M200 200 S 200.5 200.1 348.7 184.4z");

As of October 2016 path() is the only accepted value for this property in Blink browsers. However, the spec also defines the following (and we should start seeing more of these soon behind a flag in Blink).

  • A basic shape such as circle, polygon, ellipse, and inset. These should look familiar to you if you have tried using CSS Shapes.
  • A path that already exists in the document via url(), referencing the path's id.
  • An angle (this is new to the spec). You can specify any valid angle (such as 45deg) that will create a line on that angle along which to move. The end of the new line path will depend on the containing element. For now the best description is in the spec.

offset-distance

To specify where an object appears on the path we use offset-distance. This can either be any length value, but in my mind the most useful is a percentage. So to animate from the starting point of the path to the end we set up an animation that goes from 0 to 100%. With CSS Keyframes:

  @keyframes path-animation {
  0% { 
    offset-distance: 0;
  }
  100% { 
    offset-distance: 100%;
  }
}

Or with the Web Animations API in JavaScript:

  m.animate([
    { offsetDistance: 0 },
    { offsetDistance: '100%' }
  ], 1000);

offset-rotate

The direction the object “faces” is handled by the offset-rotate property. Currently, there are a few possible values to manage this:

  • The value "auto" means the element will rotate with the path.
  • "auto Xdeg" will do the same except add X degrees
  • "Xdeg" will no longer rotate with the path, the element will stay fixed facing the same direction.

This demo shows examples for these options

What Else?

There are two new properties without motion-* equivalents: offset-anchor and offset-position.

offset-anchor will allow you to change the point that is fixed as the "anchor" to the path. Currently it is in the center, but you might want it hinged to a different point, such as the top right corner.

offset-position defines where the path begins in relation to the topleft corner of the containing block.

To see what is supported in your current browser (and if it is the latest spec), I've set up a demo page

So... Should I Use it Now?

Try it now. Play with it now. Experiment with it now. Find things that are great. Find things that are weird.

The biggest drawback to motion paths right now to me, and something I've not seen discussed much, is how it depends on fixed units. I can make an SVG image responsive thanks to it having its own coordinate system, and its motion path animation will scale appropriately via SMIL or even this new CSS motion path module. But when using a path in CSS on DOM elements, we are stuck with pixel values. A path that has a horizontal length of 500 will be 500 pixels. As far as I can tell the best way to handle this today is to scale the parent container to the width you want - but that is a hack and not a real solution. This might be a place where a viewBox property on the containing element could help (but that is a property that exists only in spec discussions). I've put together my best attempt at getting something close to responsive... but it requires JS and uses a throttled resize event listener.

So for now, have fun and make some optical illusions.

Or think of how you could use motion paths to enhance a product page's hero section.

Or, if you're like me, just iterate a lot with spirals.

For more CSS Motion Path examples, when I find others experimenting I add them to this CSS Motion Path collection. I also have a collection specifically for my demos.