Shape master Temani Afif has what might be the largest collection of CSS shapes on the planet with all the tools to generate them on the fly. There’s a mix of clever techniques he’s typically used to make those shapes, many of which he’s covered here at CSS-Tricks over the years.
Some of the more complex shapes were commonly clipped with the path() function. That makes a lot of sense because it literally accepts SVG path coordinates that you can draw in an app like Figma and export.
But Temani has gone all-in on the newly-released shape() function which recently rolled out in both Chromium browsers and Safari. That includes a brand-new generator that converts path() shapes in shape() commands instead.
So, if we had a shape that was originally created with an SVG path, like this:
.shape {
clip-path: path(
M199.6,18.9
c-4.3-8.9-12.5-16.4-22.3-17.8
c-11.9-1.7-23.1,5.4-32.2,13.2
c-9.1,7.8-17.8,16.8-29.3,20.3
c-20.5,6.2-41.7-7.4-63.1-7.5
c38.7,27,24.8,33,15.2,43.3
c-35.5,38.2-0.1,99.4,40.6,116.2
c32.8,13.6,72.1,5.9,100.9-15
c27.4-19.9,44.3-54.9,47.4-88.6
c0.2-2.7,0.4-5.3,0.5-7.9
c204.8,38,203.9,27.8,199.6,18.9
z
);
}
…the generator will spit this out:
.shape {
clip-path: shape(
from 97.54% 10.91%,
curve by -10.93% -10.76% with -2.11% -5.38%/-6.13% -9.91%,
curve by -15.78% 7.98% with -5.83% -1.03%/-11.32% 3.26%,
curve by -14.36% 12.27% with -4.46% 4.71%/-8.72% 10.15%,
curve by -30.93% -4.53% with -10.05% 3.75%/-20.44% -4.47%,
curve to 7.15% 25.66% with 18.67% 15.81%/11.86% 19.43%,
curve by 19.9% 70.23% with -17.4% 23.09%/-0.05% 60.08%,
curve by 49.46% -9.07% with 16.08% 8.22%/35.34% 3.57%,
curve by 23.23% -53.55% with 13.43% -12.03%/21.71% -33.18%,
curve by 0.25% -4.77% with 0.1% -1.63%/0.2% -3.2%,
curve to 97.54% 10.91% with 100.09% 22.46%/99.64% 16.29%,
close
);
}
Pretty cool!
Honestly, I’m not sure how often I’ll need to convert path() to shape(). Seems like a stopgap sorta thing where the need for it dwindles over time as shape() is used more often — and it’s not like the existing path() function is broken or deprecated… it’s just different. But still, I’m using the generator a LOT as I try to wrap my head around shape() commands. Seeing the commands in context is invaluable which makes it an excellent learning tool.
Why is the syntax so convoluted ? Couldn’t we have the same syntax as path, but with relative units ?
I think this will be super useful when browser support gets better.
I can see a use case for it with my inverted border raduis generator: corner-inverter
While it’s a neat tool they took the time to make and I don’t wanna be a hater..
Why generate MORE CODE that has even LESS SUPPORT!?!
Seems like a solution to a problem no one has.
But whaddoIknow ♂️.
I hear ya. I think that’s just because we’re in the process of transitioning now that there’s a sparkly new feature to play with. I personally think the
shape()is better (in my limited use with it) and the support part will resolve itself over time. :)I’m interested to know what the use cases are for this technique.
I’m in desktop Safari / iOS purgatory this morning, trying to resolve iOS 18+ issues with mask-image. My SVG works great everywhere, iOS included…but iOS 18 said nope. I thought I’d found the answer with this conversion tool, but desktop Safari…said nope.
Hmm, for me the path( ) function still seems preferable to shape( ) since I currently draw everything by hand using coordinates. And that’s largely because my application has very limited space (typically less than 1k) for the SVG payload. But this option still seems powerful so thanks!