Create a Responsive CSS Motion Path? Sure We Can!

Create a Responsive CSS Motion Path? Sure We Can! css-tricks.com3 months ago in #Dev Love63

There was a discussion recently on the Animation at Work Slack: how could you make a CSS motion path responsive? What techniques would be work? This got me thinking. A CSS motion path allows us to animate elements along custom user-defined paths. Those paths follow the same structure as SVG paths. We define a path for an element using offset-path. .block {   offset-path: path(‘M20,20 C20,100 200,0 200,100’); } These values appear relative at first and they would be if we were using SVG. But, when used in an offset-path, they behave like px units. This is exactly the problem. Pixel units aren’t really responsive. This path won’t flex as the element it is in gets smaller or larger. Let’s figure this out. To set the stage, the offset-distance property dictates where an element should be on that path: Not only can we define the distance an element is along a path, but we can also define an element’s rotation with offset-rotate. The default value is auto which results in our element following the path. Check out the property’s almanac article for more values. To animate an element along the path, we animate the offset-distance: OK, that catches up to speed on moving elements along a path. Now we have to answer… Can we make responsive paths? The sticking point with CSS motion paths is the hardcoded nature. It’s not flexible. We are stuck hardcoding paths for particular dimensions and viewport sizes. A path that animates an element 600px, will animate that element 600px regardless of whether the viewport is 300px or 3440px wide. This differs from what we are familiar with when using SVG paths. They will scale with the size of the SVG viewbox. Try resizing this next demo below and you’ll see: The SVG will scale with the viewport size as will the contained path. The offset-path does not scale and the element goes off course. This could be okay for simpler paths. But once our paths become more complicated, it will be hard to maintain. Especially if we wish to use paths we’ve created in vector drawing applications. For example, consider the path we worked with earlier: .element {   –path: ‘M20,20 C20,100 200,0 200,100’;   offset-path: path(var(–path)); } To scale that up to a different container size, we would need to work out the path ourselves, then apply that path at different breakpoints. But even with this “simple” path, is it a case of multiplying all the path values? Will that give us the right scaling? @media(min-width: 768px) {   .element {     –path: ‘M40,40 C40,200 400,0 400,200’; // ????   } } A more complex path such as one drawn in a vector application is going to be trickier to maintain. It will need the developer to open the application, rescale the path, export it, and integrate it with the CSS. This will need to happen for all container size variations. It’s not the worst solution, but it does require a level of maintenance that we might not want to get ourselves into. .element {   –path: ‘M40,228.75L55.729166666666664,197.29166666666666C71.45833333333333,165.83333333333334,102.91666666666667,102.91666666666667,134.375,102.91666666666667C165.83333333333334,102.91666666666667,197.29166666666666,165.83333333333334,228.75,228.75C260.2083333333333,291.6666666666667,291.6666666666667,354.5833333333333,323.125,354.5833333333333C354.5833333333333,354.5833333333333,386.0416666666667,291.6666666666667,401.7708333333333,260.2083333333333L417.5,228.75’;   offset-path: path(var(–path)); } 
 @media(min-width: 768px) {   .element {     –path: ‘M40,223.875L55.322916666666664,193.22916666666666C70.64583333333333,162.58333333333334,101.29166666666667,101.29166666666667,131.9375,101.29166666666667C162.58333333333334,101.29166666666667,193.22916666666666,162.58333333333334,223.875,223.875C254.52083333333334,285.1666666666667,285.1666666666667,346.4583333333333,315.8125,346.4583333333333C346.4583333333333,346.4583333333333,377.1041666666667,285.1666666666667,392.4270833333333,254.52083333333334L407.75,223.875’;   } } 
 @media(min-width: 992px) {   .element {     –path: ‘M40,221.625L55.135416666666664,191.35416666666666C70.27083333333333,161.08333333333334,100.54166666666667,100.54166666666667,130.8125,100.54166666666667C161.08333333333334,100.54166666666667,191.35416666666666,161.08333333333334,221.625,221.625C251.89583333333334,282.1666666666667,282.1666666666667,342.7083333333333,312.4375,342.7083333333333C342.7083333333333,342.7083333333333,372.9791666666667,282.1666666666667,388.1145833333333,251.89583333333334L403.25,221.625’;   } } It feels like a JavaScript solution makes sense here. GreenSock is my first thought because its MotionPath plugin can scale SVG paths. But what if we want to animate outside of an SVG?  » Read More

Like to keep reading?

This article first appeared on If you'd like to keep reading, follow the white rabbit.

View Full Article

Leave a Reply