Is there any way to make a squircle but also have the border, shadow, or inner glow also conform to the squircle shape?
Creating a squircle can be done with houdini via a CSS paintWorklet
, but this has very poor support from browsers with usage being only 71.35% (2023) perhaps because of security vulnerabilities regarding the paint worklet.
Other alternatives include using an SVG <clipPath>
with the squircle shape, but adding a squircle border has to be redrawn with the original clip path, making transformations difficult. The stroke path and clip path would need to be re-rendered as the element is scaled. The CSS properties of the element would need to be converted into a path data.
<svg xmlns="http://www.w3.org/2000/svg" width="220" height="220" viewBox="-10 -10 220 220">
<defs>
<clipPath id="squircle-clip">
<path d="M20,0
L180,0
Q200,0 200,20
L200,180
Q200,200 180,200
L20,200
Q0,200 0,180
L0,20
Q0,0 20,0"
style="vector-effect: non-scaling-stroke;"
/>
</clipPath>
</defs>
<rect x="0" y="0" width="200" height="200" fill="#222" clip-path="url(#squircle-clip)"
/>
<path d="M20,0
L180,0
Q200,0 200,20
L200,180
Q200,200 180,200
L20,200
Q0,200 0,180
L0,20
Q0,0 20,0"
fill="none" stroke="#484848" stroke-width="2" style="vector-effect: non-scaling-stroke;"
/>
</svg>
Are there alternative methods to create a squircle with a border? Houdini is a hard solution to choose as it only has ~71% of all users, and without support for Safari (iOS & macOS) or Firefox.
2
Answers
This can be done easy with a div and
border-radius
+border
, you can even add a glow effect to itSquircle based on
<rect>
with<rx>
You might use a
<rect>
element with a border radius applied viarx
,ry
attributes.You can easily change width and height of a
<rect>
while maintaining the desired border-radius.Convert
<rect>
to<path>
Converting it to a
<path>
can be achieved e.g usinggetPathData()
polyfill.See also "SVG – Convert all shapes/primitives to " for more details.
Converting transformations to pathdata
First we need to get the rect’s transform "total" matrix i.e respecting all parent transformation (e.g from
<g>
) elements.I’m using a
getTransformToElement
polyfill/helper methodOnce we have the retrieved the rect’s pathdata, we can recalculate all command coordinates via
matrixTransform()
.It’s crucial to normalize the pathData first i.e we need
S
toC
)A
(arc) commands must be converted to cubicC
béziers (it might be possible to write a special conversion keeping arc commands – but it’s more complicated especially when it comes to transformations like skew.Normalizing can be done by adding the normalize parameter like so: