Sections
New this week: 38 titlesReturn by November 12
Three 110 px cards cut as a true superellipse (|x|⁴ + |y|⁴ = 1, 64 points in clip-path: polygon()), each resting on a blurred shadow of its own color: the continuous curve of phone icons, in plain CSS, with no SVG and no id.
Updated
This effect is free — the Glassmorphism category contains 47 effects total, including 6 free. Effect.Labs has 840 vanilla effects. Explore the category →
New this week: 38 titlesReturn by November 12
Hello Maëlle — courts 2 and 5 are free at 6 pm
Courts open 8 am – 10 pmDry court · 14 °C
Autumn collection: 42 pieces sewn in Roubaix and Cholet
Made in FranceFree repairs for 2 yearsReturns within 30 days
Each .squircle-card (110 × 110 px, 135° gradient, white 12 px text at weight 600) is cut by clip-path: var(--sqc-squircle). The variable, declared on the card itself, holds a polygon() of 64 points in percentages computed on the superellipse of exponent 4: curvature changes smoothly from the side into the corner, where a border-radius chains a straight line and a quarter circle. The shape removes 7.3% of the box area (computed); at the corner, the edge sits 8.8 px from the angle on each axis. Measured in Chromium 151, Firefox 153 and WebKit 26: the point 2 px from the corner does not get the click, it falls through to the parent. In percentages, the shape follows the card size: at 142 px in the second scene it is still a superellipse.
Colors go through two variables set on the .squircle-card-shadow wrapper: style="--sqc-from: #6366f1; --sqc-to: #8b5cf6;". The card paints linear-gradient(135deg, var(--sqc-from), var(--sqc-to)) var(--sqc-from) — a gradient laid over a flat color, which keeps the white text readable wherever gradients do not show. The shadow is the wrapper's ::after: 94 × 20 px, 6 px below the card, same gradient, border-radius: 50%, filter: blur(12px), opacity 0.4, z-index: -1; isolation: isolate on the wrapper keeps it above the page background. On hover the card rises 4 px, grows 8% and brightens 15% over 0.4 s, with a slight bounce (cubic-bezier(0.34, 1.56, 0.64, 1)).
Why the shape is written in CSS (--sqc-squircle: polygon(…)) rather than in an SVG <clipPath> called by clip-path: url(#squircle): such a call only works if the SVG is present on the page, with a unique id; without it, the cards show as squares (measured: 0% of the area cut, corner clickable). In CSS there is nothing to add, and several effects pasted into one page cannot collide. Two details go with it: the gradient is carried by the card itself, not by a wrapper that would paint a rectangle behind the cut shape, and the colored shadow lives in its own stacking context — at z-index: -1 without one, it would slip under the page background and never show.
#6366f1 (borderline), 3.53:1 on #ec4899, 2.43:1 on #06b6d4. Only the first card nearly passes. Darken --sqc-from: the scenes on this page use #6d28d9, #be123c, #0f766e or #1d4ed8, all above 5:1.divs with cursor: pointer, no role and no tabindex — Tab never stops on them (measured). For clickable shortcuts, turn .squircle-card into an <a> or a <button>; note that clip-path also clips the focus ring: give one to the wrapper (.squircle-card-shadow:focus-within { outline: 2px solid; outline-offset: 4px }). The icons (⚙ ♥ ★) are read aloud: aria-hidden="true" on .sq-icon.@media (prefers-reduced-motion: reduce) { .squircle-card { transition: none } .squircle-card:hover { transform: none } }.CSS only: clip-path: polygon() in percentages, custom properties (--sqc-*), gradients, filter: blur() and brightness(), isolation. Zero JavaScript, zero SVG, zero dependencies. Measured pasted into a blank page: identical shape in Chromium 151, Firefox 153 and WebKit 26 (Safari), corner outside the clickable area in all three.
Without clip-path on HTML elements (Safari before 13.1 without the -webkit-clip-path prefix, Firefox before 54), the card shows square, content and colors intact. For Safari 9 to 13: add -webkit-clip-path: var(--sqc-squircle) next to the original line.
Copy the three blocks into your page. No dependencies.
<div class="squircle-cards-wrap">
<div class="squircle-card-shadow" style="--sqc-from: #6366f1; --sqc-to: #8b5cf6;">
<div class="squircle-card"><span class="sq-icon">⚙</span>Settings</div>
</div>
<div class="squircle-card-shadow" style="--sqc-from: #ec4899; --sqc-to: #f43f5e;">
<div class="squircle-card"><span class="sq-icon">♥</span>Health</div>
</div>
<div class="squircle-card-shadow" style="--sqc-from: #06b6d4; --sqc-to: #3b82f6;">
<div class="squircle-card"><span class="sq-icon">★</span>Photos</div>
</div>
</div>
/* Formes en clip-path: polygon(), sans SVG ni id : Superellipse n = 4 (|x|^4 + |y|^4 = 1), 64 points en % de la carte. */
.squircle-card {
--sqc-squircle: polygon(0% 50%, 0.1% 34.3%, 0.5% 27.9%, 1.1% 23.1%, 1.9% 19.1%, 3% 15.7%, 4.4% 12.7%, 6% 10.2%, 8% 8%, 10.2% 6%, 12.7% 4.4%, 15.7% 3%, 19.1% 1.9%, 23.1% 1.1%, 27.9% 0.5%, 34.3% 0.1%, 50% 0%, 65.7% 0.1%, 72.1% 0.5%, 76.9% 1.1%, 80.9% 1.9%, 84.3% 3%, 87.3% 4.4%, 89.8% 6%, 92% 8%, 94% 10.2%, 95.6% 12.7%, 97% 15.7%, 98.1% 19.1%, 98.9% 23.1%, 99.5% 27.9%, 99.9% 34.3%, 100% 50%, 99.9% 65.7%, 99.5% 72.1%, 98.9% 76.9%, 98.1% 80.9%, 97% 84.3%, 95.6% 87.3%, 94% 89.8%, 92% 92%, 89.8% 94%, 87.3% 95.6%, 84.3% 97%, 80.9% 98.1%, 76.9% 98.9%, 72.1% 99.5%, 65.7% 99.9%, 50% 100%, 34.3% 99.9%, 27.9% 99.5%, 23.1% 98.9%, 19.1% 98.1%, 15.7% 97%, 12.7% 95.6%, 10.2% 94%, 8% 92%, 6% 89.8%, 4.4% 87.3%, 3% 84.3%, 1.9% 80.9%, 1.1% 76.9%, 0.5% 72.1%, 0.1% 65.7%);
}
.squircle-cards-wrap {
display: flex;
gap: 14px;
align-items: center;
justify-content: center;
flex-wrap: wrap;
padding: 10px;
}
.squircle-card {
width: 110px;
height: 110px;
background: linear-gradient(135deg, var(--sqc-from, #6366f1), var(--sqc-to, #8b5cf6)) var(--sqc-from, #6366f1);
clip-path: var(--sqc-squircle);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: white;
font-weight: 600;
font-size: 0.75rem;
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), filter 0.3s ease;
cursor: pointer;
position: relative;
}
.squircle-card:nth-child(2) {
background: linear-gradient(135deg, #ec4899, #f43f5e);
}
.squircle-card:nth-child(3) {
background: linear-gradient(135deg, #06b6d4, #3b82f6);
}
.squircle-card .sq-icon {
font-size: 1.8rem;
margin-bottom: 4px;
}
.squircle-card:hover {
transform: scale(1.08) translateY(-4px);
filter: brightness(1.15);
}
.squircle-card-shadow {
width: 110px;
height: 110px;
position: relative;
isolation: isolate;
}
.squircle-card-shadow::after {
content: '';
position: absolute;
bottom: -6px;
left: 8px;
right: 8px;
height: 20px;
background: linear-gradient(135deg, var(--sqc-from, #6366f1), var(--sqc-to, #8b5cf6));
border-radius: 50%;
filter: blur(12px);
opacity: 0.4;
z-index: -1;
}
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Colors (HTML — style="--sqc-from: …; --sqc-to: …;" on .squircle-card-shadow) |
indigo → violet, pink → red, cyan → blue | Both variables color the card AND its shadow. --sqc-from is also the flat color under the gradient: it is what matters for white text contrast. Without the variables, the card uses #6366f1 → #8b5cf6. |
Curvature (CSS — --sqc-squircle on .squircle-card) |
superellipse n = 4, 64 points | For another exponent, recompute the 64 points in the console with n defined: Array.from({length: 64}, (_, i) => { const t = Math.PI + i * Math.PI / 32, c = Math.cos(t), s = Math.sin(t), e = 2 / n; return (50 + 50 * Math.sign(c) * Math.abs(c) ** e).toFixed(1) + '% ' + (50 + 50 * Math.sign(s) * Math.abs(s) ** e).toFixed(1) + '%'; }).join(', '), then paste the result into polygon(…). n = 3 is rounder (11.7% of the area removed), n = 5 squarer (5%). |
Size (CSS — width / height of .squircle-card and .squircle-card-shadow) |
110 × 110 px | Change both rules together: the shape is in percentages and follows. A non-square card gives a stretched superellipse (longer corners on the long side). |
Shadow (CSS — .squircle-card-shadow::after) |
94 × 20 px, 6 px under the card, blur(12px), opacity 0.4 |
opacity: .6 and bottom: -10px for a card that floats higher. Do not put a clip-path back on the shadow: the blur would be cut sharp along the shape. |
Hover (CSS — .squircle-card:hover) |
scale(1.08) translateY(-4px), brightness(1.15), 0.4 s with bounce |
scale(1.04) for a tight grid; replace the curve with ease-out to remove the bounce. |
A border-radius joins a straight side to a quarter circle: curvature jumps at once from zero to its value, and the eye sees the “break” where the rounding starts. The superellipse changes curvature continuously, from the middle of the side to the corner: it is the shape of iOS icons and of Figma's “squircles”. On a 110 px card, the corner of the n = 4 superellipse sits 8.8 px from the angle on each axis; a border-radius passing through the same point needs about 30 px, and its arc then looks softer along the sides. The difference shows most at large sizes and on flat backgrounds.
Because each card is alone in its .squircle-card-shadow wrapper: it is always the first child, so these two selectors never match. Colors come from the --sqc-from / --sqc-to variables set on the wrapper. You can delete those two rules with no visible change.
No. The code describes the shape in CSS (--sqc-squircle: polygon(…)): nothing to add, no id to keep unique, and several copies of the effect — or other effects of the same family — live side by side in one page without conflict. A clip-path: url(#squircle) pointing to a <clipPath id="squircle"> missing from the page would, on the contrary, leave the cards square with no visible error: that is why the whole cut-shape family does without it.