DEV Community

Cover image for CSS Motion Path: the end of GSAP?
Brian Neville-O'Neill
Brian Neville-O'Neill

Posted on • Originally published at blog.logrocket.com on

CSS Motion Path: the end of GSAP?

Written by Facundo Corradini✏️

CSS animations used to be quite limited.

Dealing with anything other than a very basic effect usually meant long and complex @keyframes declarations.

Furthermore, moving elements through a path required a masterful use of simultaneous translation and rotation: exactly the kind of thing that browser discrepancies would turn into nothing short of a nightmare.

To fix that hassle, developers have been turning to JS solutions since the dawn of web animation (or at least, since we decided to drop Flash, but I like to pretend that Flash never happened.)

Back in the day, moving things was one of the great uses for the good ol’ jQuery, but things could get resource-intensive in a pinch.

Then GSAP came out and gave us unlimited animation power with far better performance, which quickly turned it into an industry standard.

But CSS has been progressing too, and the recent release of Firefox 72 and Chromium-powered Edge means we can start implementing the CSS Motion Path specification that comes to solve exactly these kind of scenarios.

But does this mean we can get away with pure CSS animations and dump GSAP?

LogRocket Free Trial Banner

Positioning elements through a path

The core of the Motion Path Module is the offset-path property. It takes a path() function as its value, allowing us to define an SVG path for elements to be positioned through.

.container{
  offset-path: path('M 0 100 L 200 150 L 300 150');
}
Enter fullscreen mode Exit fullscreen mode

If you ever used CSS clip-path, this should look familiar. Essentially, it defines the points that the line goes through and the different ways it gets there.

Next up, the offset-distance property allows us to define the position of the element on its offset-path. It can take whatever CSS <length> unit (%, px, etc).

In most cases, using percentages will be the better approach.

For instance, the following code will position an element right at the middle of its offset-path.

.element{
  offset-distance: 50%;
}
Enter fullscreen mode Exit fullscreen mode

Here’s an example with various elements positioned throughout a path:

Using the path for animation

Despite what the name seems to imply, there’s no motion involved when using the properties of the Motion Path module on themselves: that part is still handled by animating the different motion path properties via transitions, CSS animations, or the Web Animations API.

Therefore, to actually move the element on the path we can use a @keyframes declaration that shifts the offset-distance.

.element{
  offset-path: path('M0,0 C40,160 60,160 100,0');
  animation: move 2000ms;
}
@keyframes move {
  100% {
    offset-distance: 100%;
  }
}
Enter fullscreen mode Exit fullscreen mode

Controlling the element’s rotation

We can also use the offset-rotate property to control how the element rotation should behave as it goes through its defined path.

The default auto value will make sure that the element always faces in the direction of the path, automatically rotating as needed. If we want to position the element through the path facing in a given direction, we can use a CSS <degree> value instead.

The following code will make sure that the element keeps it’s original orientation as it goes through the path.

.element{
  offset-rotate: 0deg;
}
Enter fullscreen mode Exit fullscreen mode

Similar to what we did with offset-position, we can control the offset-rotate throughout the keyframe declaration and have the element direction adjust accordingly.

Keep in mind that for the rotation to smoothly transition, we must declare all of them in angles; changing from a degree to auto will result in jumpy motion.

Combining both, we can get results as follows:

Animating with :hover and transitions

Remember that we can also use simple transitions to animate the motion path properties

.element:hover{
  offset-distance: 100%;
  offset-rotate: 360deg;
}
Enter fullscreen mode Exit fullscreen mode

In the following example, all elements start positioned at the beginning of their path and are animated out on hover.

Wrapping text through a path

If we try to apply the motion path properties to a text element, we’ll see that the whole text block is treated as a single piece. If what we want is for the text to wrap around the path (and potentially be animated through it) we need to make each letter behave as an individual element.

The first approach to this is actually splitting the text with an utility such as splitting.js. While this works great, it will pollute the dom with a <span> for each letter, and result in screen readers spelling out the words.

The screen-reader-friendly option is to use an actual SVG text with a textPath element.

Animating the path itself

Just like the fun stuff we do with clip-path, the path declaration of an offset-path can be animated.

To do so, we must make sure to have the same amount of nodes in every step of the animation for the browser to be able to smoothly transition between them.

If we provide different amounts of nodes in any step, the browser won’t be able to guess the in-betweens and will simply jump from one step to the next without a transition.

Upcoming features and improvements

The browsers’ current implementation of offset-path only allows us to declare a path() function for the elements to follow. According to the working draft of the spec, we should be able to use a <basic-shape> (such as circle, polygon, etc) too. So we can probably expect those in the near future.

It will also allow us to use an SVG path id as the value (e.g. offset-path: url(#my-path)), which will help us animate things through a drawn path in our HTML and let it scale accordingly.

There’s also an additional property that only Firefox has implemented so far: the offset-anchor property allows us to define the anchoring point of the element relative to it’s offset-path.

It’s default setting is 50 percent/50 percent, which means the element is centered on the path. By changing the offset-anchor, we can manipulate which part of the element stays fixed to the path, similarly to what we do with transform-origin.

A word on accessibility

I’ll be the first to admit that it’s tempting to use this new tool everywhere, but animations should be used purposely and responsibly.

Animations can trigger nausea in people with vestibular disorders, be distracting for anyone with attention disorders, or simply annoying for some users that might prefer to disable it.

So consider implementing this in a prefers-reduced-motion media query, to keep those users safe.

.element{
  offset-path: path('M0,0 C40,160 60,160 100,0');
  animation: move 2s ease-out;
}

@keyframes move {
  100% {
    offset-distance: 100%;
  }
}

@media screen and (prefers-reduced-motion: reduce){
  .element{
    animation-duration: 1ms; /* takes it immediately to the ending position */
  }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

The Motion Path module has just made CSS animations a hundred times more powerful, with many use cases that we’re just beginning to discover.

But it still has some downsides: for starters, and to address the elephant in the room, Safari doesn’t support the spec yet, which can be a deal breaker for compatibility.

It also doesn’t change the quirks of CSS animation itself, such as the complexity of writing and maintaining keyframes (specially when we need to chain and synchronize them together), and the limitation to two bezier handlers for their easing functions, which make things like bounce effects much more difficult to create and maintain than in external libraries that support multiple beziers.

So GSAP is here to stay, at least for a good while.

What Motion Path does, in my opinion, is moving the threshold at which we would switch from CSS to JS for animations quite a bit.


Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.

Alt Text

LogRocket is like a DVR for web apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web apps — Start monitoring for free.


The post CSS Motion Path: the end of GSAP? appeared first on LogRocket Blog.

Latest comments (1)

Collapse
 
timjkstrickland profile image
Tim JK Strickland

Gah, I was so excited throughout this post, and then Safari ruined everything.

Classic Safari.