{"id":6976,"date":"2025-08-30T00:47:10","date_gmt":"2025-08-30T05:47:10","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=6976"},"modified":"2025-08-30T00:47:12","modified_gmt":"2025-08-30T05:47:12","slug":"the-path-of-least-resistance-part-2","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/the-path-of-least-resistance-part-2\/","title":{"rendered":"The\u00a0`-path`\u00a0of Least Resistance (Part 2)"},"content":{"rendered":"\n<p>In the previous chapter, we explored&nbsp;<code>clip-path<\/code>&nbsp;and its power to reshape elements, cutting through the rectangular constraints of traditional elements to create circles, polygons, and complex curved shapes. We learned how to think beyond the box (literally), but everything we covered was about static shapes. About defining boundaries and staying within them.<\/p>\n\n\n\n<p>Now it&#8217;s time to break free from containment entirely. In this second part, we&#8217;re shifting from shapes that hold things in place to paths that guide movement. We&#8217;re moving from&nbsp;<code>clip-path<\/code>&nbsp;to&nbsp;<code>offset-path<\/code>, where your elements don&#8217;t get clipped into new shapes, they travel along custom routes.<\/p>\n\n\n<div class=\"box article-series\">\n  <header>\n    <h3 class=\"article-series-header\">Article Series<\/h3>\n  <\/header>\n  <div class=\"box-content\">\n            <ol>\n                      <li>\n              <a href=\"https:\/\/frontendmasters.com\/blog\/the-path-of-least-resistance-part-1\/\">The `-path` of Least Resistance (Part 1)<\/a>\n            <\/li>\n                      <li>\n              <a href=\"https:\/\/frontendmasters.com\/blog\/the-path-of-least-resistance-part-2\/\">The\u00a0`-path`\u00a0of Least Resistance (Part 2)<\/a>\n            <\/li>\n                  <\/ol>\n        <\/div>\n<\/div>\n\n\n\n<p class=\"learn-more\"><a href=\"#reduced-motion\">We talk about reduced motion<\/a> for accessibility later in this post, but not all the demos in this post implement that media query as they are specifically demonstrating a concept. It&#8217;s up to you to figure out how best implement a reduced motion version of movement for your circumstances.<\/p>\n\n\n\n<p>This isn&#8217;t about changing what your elements look like. It&#8217;s about changing how they move through space, creating motion that feels natural, intentional, and surprisingly expressive. Like these rounded squares moving along a heart-shaped path:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_PwPEVKd\/a2152f7300dc56833f6b432fda1840de\" src=\"\/\/codepen.io\/anon\/embed\/PwPEVKd\/a2152f7300dc56833f6b432fda1840de?height=450&amp;theme-id=1&amp;slug-hash=PwPEVKd\/a2152f7300dc56833f6b432fda1840de&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed PwPEVKd\/a2152f7300dc56833f6b432fda1840de\" title=\"CodePen Embed PwPEVKd\/a2152f7300dc56833f6b432fda1840de\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p class=\"learn-more\">The above demo uses <a href=\"https:\/\/caniuse.com\/mdn-css_types_basic-shape_shape\">the <code>shape()<\/code> syntax which has less browser support<\/a> than other features talked about in this series, like <code>offset-path<\/code> and <code>clip-path<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"before-the-motion\">Before the Motion<\/h2>\n\n\n\n<p>Let&#8217;s break down&nbsp;<code>offset-path<\/code>&nbsp;too. We already explored the concept of&nbsp;<strong>path<\/strong>&nbsp;extensively in the previous article, but what exactly does &#8220;<strong>offset<\/strong>&#8221; mean in this context?<\/p>\n\n\n\n<p>Here&#8217;s a crucial difference from what we\u2019ve learned previously. While&nbsp;<code>clip-path<\/code>&nbsp;works relative to the element&#8217;s own&nbsp;<strong>border-box<\/strong>,&nbsp;<code>offset-path<\/code>&nbsp;works relative to the&nbsp;<strong>containing block<\/strong>&nbsp;that establishes the context for this element. The &#8220;offset&#8221; refers to the element&#8217;s position and orientation relative to that containing block, not its own dimensions.<\/p>\n\n\n\n<p>This difference becomes clear when you see multiple elements following the same path. In this demo, three shapes travel along the exact same route. They all share the same&nbsp;<code>offset-path: inset(10px)<\/code>, which creates a rectangular path 10 pixels inward from each edge of the containing block. Note how each shape follows this identical route, even though they have completely different dimensions:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_QwjaYzW\/f369d96299537f57a61d878d1adda184\" src=\"\/\/codepen.io\/anon\/embed\/QwjaYzW\/f369d96299537f57a61d878d1adda184?height=450&amp;theme-id=1&amp;slug-hash=QwjaYzW\/f369d96299537f57a61d878d1adda184&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed QwjaYzW\/f369d96299537f57a61d878d1adda184\" title=\"CodePen Embed QwjaYzW\/f369d96299537f57a61d878d1adda184\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"values-and-coordinates\">Values and Coordinates<\/h2>\n\n\n\n<p>Just like with&nbsp;<code>clip-path<\/code>, you can define your offset paths using&nbsp;<strong>absolute units<\/strong>&nbsp;like pixels for precision, or&nbsp;<strong>relative units<\/strong>&nbsp;like percentages for responsive design, giving you granular control over how your paths relate to different parts of the containing block.<\/p>\n\n\n\n<p>You can also use&nbsp;<strong>CSS variables<\/strong>&nbsp;to make your paths dynamic, allowing you to change the route based on user interactions or other conditions. You can plug a variable in as an entire path definition, a path function attribute, or a single numeric \/ coordinate inside a path function.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-comment\">\/* entire path definition *\/<\/span>\n<span class=\"hljs-selector-tag\">offset-path<\/span>: <span class=\"hljs-selector-tag\">var<\/span>(<span class=\"hljs-selector-tag\">--route<\/span>, <span class=\"hljs-selector-tag\">none<\/span>);\n\n<span class=\"hljs-comment\">\/* function attribute *\/<\/span>\n<span class=\"hljs-selector-tag\">offset-path<\/span>: <span class=\"hljs-selector-tag\">circle<\/span>(<span class=\"hljs-selector-tag\">var<\/span>(<span class=\"hljs-selector-tag\">--radius<\/span>, 50%));\n<span class=\"hljs-selector-tag\">offset-path<\/span>: <span class=\"hljs-selector-tag\">inset<\/span>(10<span class=\"hljs-selector-tag\">px<\/span> <span class=\"hljs-selector-tag\">var<\/span>(<span class=\"hljs-selector-tag\">--inline-inset<\/span>, 20<span class=\"hljs-selector-tag\">px<\/span>) 20<span class=\"hljs-selector-tag\">px<\/span>);\n\n<span class=\"hljs-comment\">\/* single coordinate *\/<\/span>\n<span class=\"hljs-selector-tag\">offset-path<\/span>: <span class=\"hljs-selector-tag\">polygon<\/span>(0% 0%, <span class=\"hljs-selector-tag\">var<\/span>(<span class=\"hljs-selector-tag\">--x2<\/span>, 100%) 0%, 100% 100%, 0% 100%);\n<span class=\"hljs-selector-tag\">offset-path<\/span>: <span class=\"hljs-selector-tag\">shape<\/span>(<span class=\"hljs-selector-tag\">from<\/span> 0% <span class=\"hljs-selector-tag\">calc<\/span>(<span class=\"hljs-selector-tag\">var<\/span>(<span class=\"hljs-selector-tag\">--x1<\/span>, 0<span class=\"hljs-selector-tag\">px<\/span>) + 10%), <span class=\"hljs-selector-tag\">line<\/span> <span class=\"hljs-selector-tag\">to<\/span> 100% 100%);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This makes motion paths highly parameterized and easy to orchestrate, and this flexibility is what makes&nbsp;<code>offset-path<\/code>&nbsp;so powerful for creating engaging, interactive experiences.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_gbaoVKR\/3547510b837489a252766f70e337af96\" src=\"\/\/codepen.io\/anon\/embed\/gbaoVKR\/3547510b837489a252766f70e337af96?height=450&amp;theme-id=1&amp;slug-hash=gbaoVKR\/3547510b837489a252766f70e337af96&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed gbaoVKR\/3547510b837489a252766f70e337af96\" title=\"CodePen Embed gbaoVKR\/3547510b837489a252766f70e337af96\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p class=\"learn-more\">You can also use CSS variables on any of the companion properties (<code>offset-distance<\/code>,&nbsp;<code>offset-rotate<\/code>,&nbsp;<code>offset-anchor<\/code>,&nbsp;<code>offset-position<\/code>) that will talk about next.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"traveling-the-distance\">Traveling the Distance<\/h2>\n\n\n\n<p>In the previous examples, we&#8217;ve seen shapes moving along heart-shaped curves, simple rectangles, and basic circles. But what exactly is moving there? You might be surprised to learn that all of them use exactly the same keyframes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@keyframes<\/span> offset {\n  0% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">0%<\/span>; }\n  100% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">100%<\/span>; }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The&nbsp;<code>offset-path<\/code>&nbsp;is actually static, it defines the path itself. The&nbsp;<code>offset-distance<\/code>&nbsp;property determines where the shape sits along that path. The position can be set as an absolute value or as a percentage, where 0% is the starting point of the path and 100% is the end. It&#8217;s the animation between these values that creates the motion along the path.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"beyond-linear-motion\">Beyond Linear Motion<\/h2>\n\n\n\n<p>Of course, the animation doesn&#8217;t have to be linear from 0 to 100. You can move the shape along the path however you want by setting the position at the appropriate keyframe. Here&#8217;s an example where I move two stars on a star-shaped path. Both share the same&nbsp;<code>offset-path<\/code>, the red star&#8217;s animation is linear, and the cyan star uses additional keyframes that move it back and forth along the path.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-comment\">\/* Red star *\/<\/span>\n<span class=\"hljs-keyword\">@keyframes<\/span> offset1 {\n  0% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">0%<\/span>; }\n  100% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">100%<\/span>; }\n}\n\n<span class=\"hljs-comment\">\/* Cyan star *\/<\/span>\n<span class=\"hljs-keyword\">@keyframes<\/span> offset2 {\n  0% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">0%<\/span>; }\n  10% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">10%<\/span>; }\n  5%, 20% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">20%<\/span>; }\n  15%, 30% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">30%<\/span>; }\n  25%, 40% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">40%<\/span>; }\n  35%, 50% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">50%<\/span>; }\n  45%, 60% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">60%<\/span>; }\n  55%, 70% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">70%<\/span>; }\n  65%, 80% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">80%<\/span>; }\n  75%, 90% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">90%<\/span>; }\n  85%, 100% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">100%<\/span>; }\n  95% { <span class=\"hljs-attribute\">offset-distance<\/span>: <span class=\"hljs-number\">110%<\/span>; }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_dPYdbMW\/1907074f3b87ef255044edf3544dd68f\" src=\"\/\/codepen.io\/anon\/embed\/dPYdbMW\/1907074f3b87ef255044edf3544dd68f?height=450&amp;theme-id=1&amp;slug-hash=dPYdbMW\/1907074f3b87ef255044edf3544dd68f&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed dPYdbMW\/1907074f3b87ef255044edf3544dd68f\" title=\"CodePen Embed dPYdbMW\/1907074f3b87ef255044edf3544dd68f\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p class=\"learn-more\">Note that this animation uses a keyframe with&nbsp;<code>offset-distance: 110%<\/code>, and we&#8217;ll talk about negative and overflow distances later in this article.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"interactive-movement\">Interactive Movement<\/h2>\n\n\n\n<p>But you&#8217;re not limited to keyframe animations. You can also use&nbsp;<code>transition<\/code>&nbsp;to smoothly animate the&nbsp;<code>offset-distance<\/code>&nbsp;property in response to different states and user interactions like hover, click, or focus. Like in this example where I set the&nbsp;<code>offset-distance<\/code>&nbsp;based on which element is being hovered.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_GgpQKNx\/056532451c30f6eb3d3790b0e67a7ff6\" src=\"\/\/codepen.io\/anon\/embed\/GgpQKNx\/056532451c30f6eb3d3790b0e67a7ff6?height=450&amp;theme-id=1&amp;slug-hash=GgpQKNx\/056532451c30f6eb3d3790b0e67a7ff6&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed GgpQKNx\/056532451c30f6eb3d3790b0e67a7ff6\" title=\"CodePen Embed GgpQKNx\/056532451c30f6eb3d3790b0e67a7ff6\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"finding-your-anchor\">Finding Your Anchor<\/h2>\n\n\n\n<p>Here&#8217;s something that trips up a lot of people when they first start working with&nbsp;<code>offset-path<\/code>: which part of your element actually travels along the path? By default, it&#8217;s the center of the element, but that&#8217;s not always what you want.<\/p>\n\n\n\n<p>The&nbsp;<code>offset-anchor<\/code>&nbsp;property lets you specify which point on your element gets aligned with the path. You can anchor from any corner, edge, or specific coordinate within the element. It works just like&nbsp;<code>transform-origin<\/code>, accepting keywords like&nbsp;<code>center<\/code>,&nbsp;<code>top left<\/code>, or specific values like&nbsp;<code>75% 25%<\/code>. This seemingly small detail can completely transform how your animations act and feel.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_vENdNZP\/d26ca8fd4ab5d0b22be4a086470af86a\" src=\"\/\/codepen.io\/anon\/embed\/vENdNZP\/d26ca8fd4ab5d0b22be4a086470af86a?height=450&amp;theme-id=1&amp;slug-hash=vENdNZP\/d26ca8fd4ab5d0b22be4a086470af86a&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed vENdNZP\/d26ca8fd4ab5d0b22be4a086470af86a\" title=\"CodePen Embed vENdNZP\/d26ca8fd4ab5d0b22be4a086470af86a\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"setting-the-starting-point\">Setting the Starting Point<\/h2>\n\n\n\n<p>Another piece of the puzzle that&#8217;s often overlooked is deciding where the path begins. While&nbsp;<code>offset-anchor<\/code>&nbsp;controls which part of your element follows the path,&nbsp;<code>offset-position<\/code>&nbsp;determines where that path starts within the containing block.<\/p>\n\n\n\n<p>This is particularly important when you&#8217;re using path functions that don&#8217;t specify their own starting position. The default value is&nbsp;<code>normal<\/code>, which places the starting point at the center of the containing block (<code>50% 50%<\/code>). But you can position it anywhere you want.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_XJmYKRm\/b7627606c2c484f39393b3a1bc574990\" src=\"\/\/codepen.io\/anon\/embed\/XJmYKRm\/b7627606c2c484f39393b3a1bc574990?height=450&amp;theme-id=1&amp;slug-hash=XJmYKRm\/b7627606c2c484f39393b3a1bc574990&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed XJmYKRm\/b7627606c2c484f39393b3a1bc574990\" title=\"CodePen Embed XJmYKRm\/b7627606c2c484f39393b3a1bc574990\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>With&nbsp;<code>offset-position: auto<\/code>, the path uses the element\u2019s&nbsp;<strong>own box position<\/strong>&nbsp;as the path\u2019s origin. With something like&nbsp;<code>offset-position: 60px 90px<\/code>, the path starts from that specific position within the containing block, regardless of where the element itself is positioned.<\/p>\n\n\n\n<p>This gives you incredible flexibility in designing motion paths. You can have multiple elements starting from different points but following similar route shapes, or create complex choreographed movements where the starting positions are as carefully controlled as the paths themselves.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"following-the-flow\">Following the Flow<\/h2>\n\n\n\n<p>But there&#8217;s another crucial piece to making path animations feel natural: rotation. The&nbsp;<code>offset-rotate<\/code>&nbsp;property controls exactly this. It can automatically rotate your element to match the direction of the path at any given point, or you can set a fixed rotation, or combine both for more complex effects.<\/p>\n\n\n\n<p>The magic keyword here is&nbsp;<code>auto<\/code>. When set, your element will always face the direction it&#8217;s traveling. As it moves around curves and corners, it rotates to stay aligned with the path&#8217;s tangent. You can set a fixed angle to override this automatic rotation, or combine a fixed angle with auto direction, like this:&nbsp;<code>offset-rotate: auto 45deg<\/code>. It means &#8220;face the direction of travel, but add an extra 45-degree twist.&#8221;<\/p>\n\n\n\n<p>Here&#8217;s a perfect example to illustrate the different rotation behaviors. Four arrows travel along the same curved path, but each one demonstrates a different approach to rotation:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_GgpQpwg\/8741f2f3ec8799b0b0baa197edee9478\" src=\"\/\/codepen.io\/anon\/embed\/GgpQpwg\/8741f2f3ec8799b0b0baa197edee9478?height=450&amp;theme-id=1&amp;slug-hash=GgpQpwg\/8741f2f3ec8799b0b0baa197edee9478&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed GgpQpwg\/8741f2f3ec8799b0b0baa197edee9478\" title=\"CodePen Embed GgpQpwg\/8741f2f3ec8799b0b0baa197edee9478\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>The red arrow uses the standard&nbsp;<code>auto<\/code>&nbsp;behavior, always pointing in the direction of travel. The green arrow ignores the path direction entirely with a fixed&nbsp;<code>60deg<\/code>&nbsp;rotation. The cyan arrow combines both approaches with&nbsp;<code>auto 30deg<\/code>, following the path but with an additional 30-degree offset. And the purple arrow uses&nbsp;<code>reverse<\/code>, pointing backward along the path as if it&#8217;s being pulled rather than leading.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"working-with-transforms\">Working With Transforms<\/h2>\n\n\n\n<p>Here&#8217;s where things get really interesting from a technical perspective. When you use&nbsp;<code>offset-path<\/code>, you&#8217;re not positioning the elements, you&#8217;re actually&nbsp;<strong>transforming<\/strong>&nbsp;them into their place and angle, very much like using&nbsp;<code>translate()<\/code>&nbsp;and&nbsp;<code>rotate()<\/code>. This special type of CSS transform is called an &#8220;offset transform&#8221;, it&#8217;s a distinct layer in the transform stack, and it sits in a very specific position.<\/p>\n\n\n\n<p>The transform order looks like this:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Individual transform properties (<code>translate<\/code>, <code>rotate<\/code>, <code>scale<\/code>)<\/li>\n\n\n\n<li>Offset transform (our <code>offset-path<\/code> magic happens here)<\/li>\n\n\n\n<li>The <code>transform<\/code> property<\/li>\n<\/ol>\n\n\n\n<p>This layering is crucial because it means&nbsp;<code>offset-path<\/code>&nbsp;transforms are applied&nbsp;<em>after<\/em>&nbsp;individual transform properties but&nbsp;<em>before<\/em>&nbsp;the&nbsp;<code>transform<\/code>&nbsp;property. This can significantly change the final visual result.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_zxvRrPX\/4fe4f095c5ef299945d7485bdc1ea4c0\" src=\"\/\/codepen.io\/anon\/embed\/zxvRrPX\/4fe4f095c5ef299945d7485bdc1ea4c0?height=450&amp;theme-id=1&amp;slug-hash=zxvRrPX\/4fe4f095c5ef299945d7485bdc1ea4c0&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed zxvRrPX\/4fe4f095c5ef299945d7485bdc1ea4c0\" title=\"CodePen Embed zxvRrPX\/4fe4f095c5ef299945d7485bdc1ea4c0\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>The first three use the individual transform properties: one&nbsp;<code>translate<\/code>, one&nbsp;<code>rotate<\/code>, one&nbsp;<code>scale<\/code>. The other three use the&nbsp;<code>transform<\/code>&nbsp;property: one&nbsp;<code>translate()<\/code>, one&nbsp;<code>rotate()<\/code>, one&nbsp;<code>scale()<\/code>. Because the individual transform properties run before the offset transform and the&nbsp;<code>transform<\/code>&nbsp;property runs after it, you get six different visual results from the same path.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"performance-considerations\">Performance Considerations<\/h2>\n\n\n\n<p>The good thing about&nbsp;<code>offset-path<\/code>&nbsp;being a part of the transform stack is that it leverages the same hardware acceleration as other CSS transforms. The browser calculates the path geometry once, then efficiently interpolates positions and rotations as needed. No repaints or reflows.<\/p>\n\n\n\n<p>But there are a few performance gotchas to watch out for. Avoid changing the&nbsp;<code>offset-path<\/code>&nbsp;itself during animations, as it forces expensive recalculations. Instead, animate&nbsp;<code>offset-distance<\/code>&nbsp;and use CSS variables or classes to switch between different paths.<\/p>\n\n\n\n<p>Also, be mindful of path complexity. Don&#8217;t use&nbsp;<code>shape()<\/code>&nbsp;for a simple straight line, and remember that a&nbsp;<code>circle()<\/code>&nbsp;performs much better than a&nbsp;<code>path()<\/code>&nbsp;with hundreds of curve segments. If you&#8217;re seeing performance issues, consider simplifying your paths.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"closed-vs-open-paths\">Closed vs Open Paths<\/h2>\n\n\n\n<p>There&#8217;s an important distinction in how different path functions behave when it comes to their start and end points. Some paths are inherently closed and cyclical, while others can be left open with distinct endpoints.<\/p>\n\n\n\n<p>Path functions like&nbsp;<code>circle()<\/code>,&nbsp;<code>inset()<\/code>, and&nbsp;<code>polygon()<\/code>&nbsp;always create closed paths. These are cyclical by nature, meaning the 100% position (the end) connects seamlessly back to the 0% position (the start). When an element travels along these paths, it forms a continuous loop without any jarring jumps or discontinuities.<\/p>\n\n\n\n<p>In contrast, functions like&nbsp;<code>path()<\/code>&nbsp;and&nbsp;<code>shape()<\/code>&nbsp;give you explicit control over whether the path is closed or open. With these functions, you can choose to close the path (creating that seamless loop) or leave it open. When a path is left open, there&#8217;s a distinct gap between the endpoint and the starting point. If an element travels from 100% back to 0%, it will visually &#8220;jump&#8221; from the final position directly to the starting position.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_azvKWNX\/8bcba42e699a22e9dfd94256a02ede4b\" src=\"\/\/codepen.io\/anon\/embed\/azvKWNX\/8bcba42e699a22e9dfd94256a02ede4b?height=450&amp;theme-id=1&amp;slug-hash=azvKWNX\/8bcba42e699a22e9dfd94256a02ede4b&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed azvKWNX\/8bcba42e699a22e9dfd94256a02ede4b\" title=\"CodePen Embed azvKWNX\/8bcba42e699a22e9dfd94256a02ede4b\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>In this example, all three shapes follow a similar path with just two lines, forming an inverted V shape. You can see that both the&nbsp;<code>polygon()<\/code>&nbsp;and the closed&nbsp;<code>path()<\/code>&nbsp;treat the gap between the last and first points as part of the path, even though it&#8217;s not explicitly defined that way. The middle&nbsp;<code>path()<\/code>&nbsp;remains open, so when it reaches the endpoint, it jumps directly back to the start.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"negative-and-overflow-distances\">Negative and Overflow Distances<\/h2>\n\n\n\n<p>This distinction between closed and open paths becomes particularly important when you start using&nbsp;<code>offset-distance<\/code>&nbsp;values outside the typical 0% to 100% range.<\/p>\n\n\n\n<p>For closed paths, the cyclical nature means you can use any distance value, even negative numbers or values over 100%. Since the path loops back on itself, these values get normalized to their equivalent position within the 0-100% range. An&nbsp;<code>offset-distance<\/code>&nbsp;of 120% on a closed path is equivalent to 20%, and -15% becomes 85%. The element simply continues around the loop, making multiple revolutions if needed.<\/p>\n\n\n\n<p>Open paths behave very differently. Here, distance values get clamped to the 0-100% range. Any value greater than 100% will position the element at the endpoint of the path, and any value less than 0% will keep it at the starting point. There&#8217;s no wrapping or continuation because there&#8217;s nowhere for the path to continue beyond its defined endpoints.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_MYaXoRK\/c6c632e5fe4803e632afbfe92d55d8c2\" src=\"\/\/codepen.io\/anon\/embed\/MYaXoRK\/c6c632e5fe4803e632afbfe92d55d8c2?height=450&amp;theme-id=1&amp;slug-hash=MYaXoRK\/c6c632e5fe4803e632afbfe92d55d8c2&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed MYaXoRK\/c6c632e5fe4803e632afbfe92d55d8c2\" title=\"CodePen Embed MYaXoRK\/c6c632e5fe4803e632afbfe92d55d8c2\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p><a href=\"https:\/\/codepen.io\/amit_sheen\/pen\/MYaXoRK\/c6c632e5fe4803e632afbfe92d55d8c2\"><\/a>In this demo, you can play with the distance slider, which gives you a range from -50% to 150%, and see how the different paths respond.<\/p>\n\n\n\n<p>This difference opens up interesting animation possibilities. With closed paths, you can create smooth multi-revolution animations by animating from 0% to values like 200% or 300%. With open paths, you might use values beyond the normal range to create pause effects at the endpoints, or to ensure the element stays put even if the animation overshoots.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"split-paths\">Split Paths<\/h2>\n\n\n\n<p>We&#8217;ve seen the jump between the endpoint and starting point in open paths, and while that&#8217;s not always what we want, sometimes it&#8217;s exactly what we need.<\/p>\n\n\n\n<p>Sometimes we need to interrupt the animation at one location and restart it at another, which wasn&#8217;t always straightforward until now. Using&nbsp;<code>shape()<\/code>, we can cut the motion of an animation in the middle of the path and restart it with a&nbsp;<code>move<\/code>&nbsp;command.<\/p>\n\n\n\n<p>Here&#8217;s an example of a shape I created that&#8217;s cut in the middle.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">offset-path<\/span>: <span class=\"hljs-selector-tag\">shape<\/span>(\n  <span class=\"hljs-selector-tag\">from<\/span> 80% 30%,\n  <span class=\"hljs-selector-tag\">curve<\/span> <span class=\"hljs-selector-tag\">to<\/span> 100% 50% <span class=\"hljs-selector-tag\">with<\/span> 90% 20% \/ 105% 40%,\n  <span class=\"hljs-selector-tag\">curve<\/span> <span class=\"hljs-selector-tag\">to<\/span> 100% 70% <span class=\"hljs-selector-tag\">with<\/span> 95% 60%,\n  <span class=\"hljs-selector-tag\">curve<\/span> <span class=\"hljs-selector-tag\">to<\/span> 80% 90% <span class=\"hljs-selector-tag\">with<\/span> 105% 80% \/ 90% 100%,\n  <span class=\"hljs-selector-tag\">curve<\/span> <span class=\"hljs-selector-tag\">to<\/span> 60% 90% <span class=\"hljs-selector-tag\">with<\/span> 70% 80%,\n  <span class=\"hljs-selector-tag\">move<\/span> <span class=\"hljs-selector-tag\">to<\/span> 20% 70%, <span class=\"hljs-comment\">\/* here's the cut *\/<\/span>\n  <span class=\"hljs-selector-tag\">curve<\/span> <span class=\"hljs-selector-tag\">to<\/span> 0% 50% <span class=\"hljs-selector-tag\">with<\/span> 10% 80% \/ <span class=\"hljs-selector-tag\">-5<\/span>% 60%,\n  <span class=\"hljs-selector-tag\">curve<\/span> <span class=\"hljs-selector-tag\">to<\/span> 0% 30% <span class=\"hljs-selector-tag\">with<\/span> 5% 40%,\n  <span class=\"hljs-selector-tag\">curve<\/span> <span class=\"hljs-selector-tag\">to<\/span> 20% 10% <span class=\"hljs-selector-tag\">with<\/span> <span class=\"hljs-selector-tag\">-5<\/span>% 20% \/ 10% 0%,\n  <span class=\"hljs-selector-tag\">curve<\/span> <span class=\"hljs-selector-tag\">to<\/span> 40% 10% <span class=\"hljs-selector-tag\">with<\/span> 30% 20%\n);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>And here&#8217;s how it looks if we visualize the path itself:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"910\" height=\"610\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/s_C4C4BD9B38FE52C7864331594FF600266A96201CECDAB37CFEF7ECCC3653405A_1756058683788_image.webp?resize=910%2C610&#038;ssl=1\" alt=\"Illustration of a motion path with labeled starting point, end point, and a movement command to a specific coordinate.\" class=\"wp-image-7027\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/s_C4C4BD9B38FE52C7864331594FF600266A96201CECDAB37CFEF7ECCC3653405A_1756058683788_image.webp?w=910&amp;ssl=1 910w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/s_C4C4BD9B38FE52C7864331594FF600266A96201CECDAB37CFEF7ECCC3653405A_1756058683788_image.webp?resize=300%2C201&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/s_C4C4BD9B38FE52C7864331594FF600266A96201CECDAB37CFEF7ECCC3653405A_1756058683788_image.webp?resize=768%2C515&amp;ssl=1 768w\" sizes=\"auto, (max-width: 910px) 100vw, 910px\" \/><\/figure>\n\n\n\n<p>If we take this exact path, use it to move some circles, add some styling and perspective to make them look like a colorful twisting snake of balls, and add &#8216;gates&#8217; as portals between the transition points, we get something like this:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_yyYEzdZ\/a77a80a118cd151b140966da64b3e77c\" src=\"\/\/codepen.io\/anon\/embed\/yyYEzdZ\/a77a80a118cd151b140966da64b3e77c?height=450&amp;theme-id=1&amp;slug-hash=yyYEzdZ\/a77a80a118cd151b140966da64b3e77c&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed yyYEzdZ\/a77a80a118cd151b140966da64b3e77c\" title=\"CodePen Embed yyYEzdZ\/a77a80a118cd151b140966da64b3e77c\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"infinite-directions\"><strong>Infinite Directions<\/strong><\/h2>\n\n\n\n<p>As we&#8217;re getting closer to the end of our deep dive, let&#8217;s talk about something special that exists only in&nbsp;<code>offset-path<\/code>: the&nbsp;<code>ray()<\/code>&nbsp;function.<\/p>\n\n\n\n<p>While most path functions define specific routes with clear start and end points,&nbsp;<code>ray()<\/code>&nbsp;takes a completely different approach. It creates an&nbsp;<strong>infinite<\/strong>&nbsp;straight line extending from a specified starting point in a given direction. Think of it as a laser beam that goes on forever.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">offset-path<\/span>: <span class=\"hljs-selector-tag\">ray<\/span>(<span class=\"hljs-selector-tag\">var<\/span>(<span class=\"hljs-selector-tag\">--angle<\/span>)); <\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>As you can see, the syntax is refreshingly simple. You put an\u00a0<code>&lt;angle><\/code>\u00a0inside the function, and that angle determines where the ray will point (<code>0deg<\/code> points right, <code>90deg<\/code> points down).<\/p>\n\n\n\n<p>So this covers the direction the ray is pointing, but if it&#8217;s an infinite line, what does 100% actually mean?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">100% out of infinite<\/h3>\n\n\n\n<p>The default 100% is&nbsp;<code>closest-side<\/code>, which means the distance from the ray&#8217;s starting point to the closest side is 100%. We can define this distance using an optional keyword that controls how far the ray extends before the element reaches 100% distance.<\/p>\n\n\n\n<p>There are five keywords in total:\u00a0<code>closest-side<\/code>,\u00a0<code>closest-corner<\/code>,\u00a0<code>farthest-side<\/code>,\u00a0<code>farthest-corner<\/code>, and\u00a0<code>sides<\/code>. To understand the difference between them, here&#8217;s an example where if you hover over the element, the mouse cursor position represents the ray&#8217;s starting position, and you can see what each keyword means relative to that position.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_raOKdNX\/163273867c91b17b2d1b5111beb3fe0a\" src=\"\/\/codepen.io\/anon\/embed\/raOKdNX\/163273867c91b17b2d1b5111beb3fe0a?height=450&amp;theme-id=1&amp;slug-hash=raOKdNX\/163273867c91b17b2d1b5111beb3fe0a&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed raOKdNX\/163273867c91b17b2d1b5111beb3fe0a\" title=\"CodePen Embed raOKdNX\/163273867c91b17b2d1b5111beb3fe0a\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>Notice that&nbsp;<code>sides<\/code>&nbsp;always stays constant, because it represents the distance to the element&#8217;s edge, regardless of the ray&#8217;s angle.<\/p>\n\n\n\n<p>Here&#8217;s an example that uses the&nbsp;<code>sides<\/code>&nbsp;keyword. Here too, the mouse cursor position represents the ray&#8217;s center, and from there each star animates to the closest side and back. Hover over it to see how it reacts.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_pvjKLLM\/983229b6e05f87c70b0cf35c35cdb8e5\" src=\"\/\/codepen.io\/anon\/embed\/pvjKLLM\/983229b6e05f87c70b0cf35c35cdb8e5?height=450&amp;theme-id=1&amp;slug-hash=pvjKLLM\/983229b6e05f87c70b0cf35c35cdb8e5&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed pvjKLLM\/983229b6e05f87c70b0cf35c35cdb8e5\" title=\"CodePen Embed pvjKLLM\/983229b6e05f87c70b0cf35c35cdb8e5\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>What makes&nbsp;<code>ray()<\/code>&nbsp;particularly interesting is that it&#8217;s always an open path, but unlike other open paths, there&#8217;s no defined endpoint. When you animate beyond 100%, the element just keeps traveling in that direction indefinitely. This makes it perfect for creating elements that fly off screen, laser effects, or directional animations that need to feel endless.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"reduced-motion\">Reduced Motion<\/h2>\n\n\n\n<p>Just like any other animation,&nbsp;<code>offset-path<\/code>&nbsp;animations should respect user preferences and accessibility guidelines. When users have enabled reduced motion in their system settings, it&#8217;s important to either reduce or completely disable path animations accordingly. This ensures your interactive experiences remain accessible and comfortable for all users, including those who may experience motion sensitivity or vestibular disorders.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-comment\">\/*  animate only if the user has not expressed a preference for reduced motion *\/<\/span>\n<span class=\"hljs-keyword\">@media<\/span> (<span class=\"hljs-attribute\">prefers-reduced-motion:<\/span> no-preference) {\n  <span class=\"hljs-selector-class\">.moving-shape<\/span> {\n    <span class=\"hljs-attribute\">animation<\/span>: offset <span class=\"hljs-number\">5s<\/span> linear infinite;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id=\"wrapping-up\"><strong>Wrapping Up<\/strong><\/h2>\n\n\n\n<p>And just like that, we&#8217;ve completed our journey through the&nbsp;<strong>-path<\/strong>&nbsp;universe. What started in Part 1 as static shapes carved from rectangular constraints has evolved into something far more dynamic and expressive. We learned to think beyond the traditional box with&nbsp;<code>clip-path<\/code>, mastering the art of containment. Now with&nbsp;<code>offset-path<\/code>, we&#8217;ve transcended those boundaries entirely. Your elements no longer just exist in custom shapes, they dance through space along routes you design.<\/p>\n\n\n\n<p>Together, these properties form a complete vocabulary for spatial expression in CSS.&nbsp;<code>clip-path<\/code>&nbsp;gives you control over form, while&nbsp;<code>offset-path<\/code>&nbsp;gives you control over motion. One carves space, the other travels through it. The combination unlocks interface animations that feel both natural and magical.<\/p>\n\n\n\n<p>The path of least resistance isn&#8217;t always the straight line between two points. Sometimes it&#8217;s the beautiful curve that makes the journey more meaningful than the destination. And now you have the tools to create those curves, whether they contain your elements or carry them forward into new possibilities.<\/p>\n\n\n<div class=\"box article-series\">\n  <header>\n    <h3 class=\"article-series-header\">Article Series<\/h3>\n  <\/header>\n  <div class=\"box-content\">\n            <ol>\n                      <li>\n              <a href=\"https:\/\/frontendmasters.com\/blog\/the-path-of-least-resistance-part-1\/\">The `-path` of Least Resistance (Part 1)<\/a>\n            <\/li>\n                      <li>\n              <a href=\"https:\/\/frontendmasters.com\/blog\/the-path-of-least-resistance-part-2\/\">The\u00a0`-path`\u00a0of Least Resistance (Part 2)<\/a>\n            <\/li>\n                  <\/ol>\n        <\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>This time we&#8217;re looking at offset-path (and friends), which can be used to create movement when animated and benefits from all the same fancy functions that we learned about with clip-path.<\/p>\n","protected":false},"author":27,"featured_media":7023,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[100,7,353],"class_list":["post-6976","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-animation","tag-css","tag-offset-path"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/08\/part2.jpg?fit=2100%2C1205&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/6976","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/27"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=6976"}],"version-history":[{"count":17,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/6976\/revisions"}],"predecessor-version":[{"id":7055,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/6976\/revisions\/7055"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/7023"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=6976"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=6976"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=6976"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}