I Made a Squircle Button (and of Course It’s a Web Component)
We’ve got some pretty funny names in the software industry, and a few are simply hilarious to say out loud. Try it. Squircle. I made a squircle. Ha ha! Now let’s get into the reason for it.
By Jared White
Before we get into the nitty-gritty, just what is a squircle? And how it related to a superellipse?
Here’s a definition I found from this article by Olga Nikolskaya:
The Superellipse is the name given to a family of shapes and the most popular of them is Squircle, the shape intermediate between circle and square. The appearance of squircle seems optically balanced: no sharpness, no angles…
In other words, unlike typical CSS-based “rounded corners” you see on the web where the point at which the straight side angle starts to curve is very noticeable, a squircle offers a very gradual shift from a side to a corner. This was a major topic of conversation back when Apple first released iOS 7, as Mark Stanton at HackerNoon points out:
A ‘secret’ of Apple’s physical products is that they avoid tangency (where a radius meets a line at a single point) and craft their surfaces with what’s called curvature continuity. Once you know how to spot it on products, you’re likely to start seeing it (or more likely the lack of it) all around you.
iOS 7 brought that hardware curvature to their software, but unfortunately that aesthetic never made it over to the web where we still just have a very boring (yet still extremely useful) border-radius
.
I got the idea to investigate this topic after noticing (of all things) a Help Scout Beacon button installed on a client app I was working on. I kept looking at the button and wondering why the shape of it seemed unusual to me, and it finally dawned on me that I was looking at a squircle button and not a typical button with CSS rounded corners. (You can see it in action here.)
Upon further investigation, I discovered they were using SVG shapes on the left and right sides of the button to provide the necessary curvature. That’s a pretty interesting technique, but it got me wondering if there might be another approach that, yes, still uses SVG yet not for the “endcaps” but for the entire shape of a button.
Oops I Clipped My Path #
A bit of sleuthing on DuckDuckGo turned up this fascinating article by Simeon Griggs (funny enough, he references Olga’s article I mentioned above!). The trick is to define a clipPath
inside of an SVG element, and then reference that using a clip-path
CSS property. From Simeon’s example:
<svg width="10" height="10" viewBox="0 0 10 10">
<clipPath id="squircleClip" clipPathUnits="objectBoundingBox">
<path
fill="red"
stroke="none"
d="M 0,0.5 C 0,0 0,0 0.5,0 S 1,0 1,0.5 1,1 0.5,1 0,1 0,0.5"
/>
</clipPath>
</svg>
.squircle {
clip-path: url(#squircleClip);
}
Slap that on a tag and you’ve got yourself a squircle.
I was excited to try this out on a button, so naturally there was only way I’d want to package this up into a reusable component: by building a web component. And of course, once I got the initial technique all squared (squircled?) away, I needed to take it just a few steps further.
And here’s the result! Say hello to <sq-button>
:
So yes indeed, we have that appealing shape without any sharpness to the curvature. But on top of that, I added an eye-catching gradient background (thanks oklch
!) to the button—which when you hover over it, it rotates! Whoa! How did I do that?
That’s all thanks to the magic of @property
, a way of defining typed CSS custom properties. The typing is crucial, because if you were to attempt to define a value like 135deg
for a new CSS custom property without using @property
, it wouldn’t be usable for a transition. By typing it as an angle specifically, we gain animation functionality.
@property
only recently became available across all browsers, so bear that in mind—but as a nice bit of progressively-enhanced visual flourish, I’m quite impressed!
Drop Your Shadows #
I also added a drop shadow to the button. Note that when you’re using the clip-path
technique, you can’t utilize box-shadow
any longer because the clipped element will no longer display the shadow either. derp 🤪
Thankfully, filter
is still an option for applying an SVG-based drop shadow to the host element. I made the shadow, the background gradient, and the hover animation duration all customizable using CSS variables, and if I were to spend more time with this I’d make a bunch of other aspects of the component’s appearance customizable as well.
I really like my squircle button. 🥰 I think I might introduce it to an upcoming app I plan to start working on soon, because when you’re so used to the typical “roundrect” buttons on the web, squircles really do stand out.
Future Thoughts: in a production application, I would of course use declarative shadow DOM to render out these buttons so they don’t purely rely on JavaScript to render. As you might notice, I’m not actually using JavaScript to do anything in the CodePen except to inject HTML & CSS into the shadow DOM. This might also mean I’d break out the SVG into its own external file, as well as the styles (loading them via <link>
), so that each declarative shadow DOM template is as minimal as possible. That’d require some performance testing for an optimal approach, as I’m not sure if a delay in loading an external SVG would cause any graphical glitching. That’s why this section is titled future thoughts! Welcome to how my brain works. 😅