GlassmorphismFree

Squircle Cards

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.

SVGClip-pathHover

Updated

⚙Settings
♥Health
★Photos
Hover or click the scene to interact

This effect is free — the Glassmorphism category contains 47 effects total, including 6 free. Effect.Labs has 840 vanilla effects. Explore the category →

Usage examples

Malik · 2 loans

Sections

📖Novels4,210 titles
💬Comics1,870 albums
🧸Children3,045 titles
🎧Music980 CDs and vinyls

New this week: 38 titlesReturn by November 12

① Library sections — a municipal library's app

WhenApp home screen: Novels, Comics, Children, Music, each in a colored tile, under the search field and above the loan return date.
WhyThe continuous curve of the superellipse is the one of phone icons: the four sections read like apps you tap, not like website buttons. The same-color shadow lifts each tile off the paper background with no frame or line.
SettingsFour 110 px cards instead of three, gap: 16px; colors set through --sqc-from / --sqc-to on each wrapper (#6d28d9, #be123c, #0f766e, #1d4ed8 as start colors, for white text above 5:1); number of titles in a small under the section name.
TC des PeupliersTennis club · 6 clay courts
2026-27 membership ✓

Hello Maëlle — courts 2 and 5 are free at 6 pm

🎾Book a court2 free at 6 pm
🏆Autumn tournamentEntries until Nov 8
🧢Tennis schoolWednesday 2 pm group

Courts open 8 am – 10 pmDry court · 14 °C

② Shortcuts of a tennis club — the club's app

WhenThe player opens the club app: book a court, enter the autumn tournament or find the tennis school, over the club's clay-court background.
WhyThree big tiles to tap with a thumb, looking like the icons on their phone: there is nothing else to read. The superellipse in percentages follows the size: enlarged to 142 px, the shape stays the same, with nothing to recompute.
Settings.squircle-card and its wrapper set to 142 × 142 px, icon at 2.3 rem, label at 14 px; green #15803d, navy #1e3a8a, violet #7e22ce as gradient start; an availability line (“2 free at 6 pm”) under each label.
Atelier Garance

Shop by material

Autumn collection: 42 pieces sewn in Roubaix and Cholet

🌾Linen14 pieces
🧶Recycled wool11 pieces
🌱Organic cotton17 pieces

Made in FranceFree repairs for 2 yearsReturns within 30 days

③ Categories of an ethical fashion shop

WhenAt the top of the shop, under the heading “Shop by material”: Linen, Recycled wool, Organic cotton, with the number of pieces in each.
WhyThe soft, precise shape suits a careful brand; superelliptic corners avoid the “default web button” look of a plain border-radius. The natural tones (stone, terracotta, olive) go through two variables, without touching the CSS.
Settings128 px cards, gap: 24px; --sqc-from / --sqc-to: #57534e → #a8a29e (linen), #9a3412 → #ea580c (wool), #3f6212 → #84cc16 (cotton); linen-cloth background drawn with two repeating-linear-gradient.

How it works

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.

Accessibility

  • White text contrast (12 px, weight 600: normal text, 4.5:1 threshold) measured on the start color of each gradient: 4.47:1 on #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.
  • Keyboard and screen readers: the cards are 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.
  • prefers-reduced-motion not in the code: the 4 px lift with bounce stays active under the preference (measured). The motion is short and triggered by the visitor; to remove it: @media (prefers-reduced-motion: reduce) { .squircle-card { transition: none } .squircle-card:hover { transform: none } }.

Browser compatibility

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.

Chrome 55+✓ Full
Firefox 54+✓ Full
Safari 13.1+✓ Full
Edge 79+✓ Full
Mobile iOS 13.4+✓ Full (hover becomes a tap)
Android Chrome 55+✓ Full

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.

The code

Copy the three blocks into your page. No dependencies.

HTML
<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">&#9881;</span>Settings</div>
    </div>
    <div class="squircle-card-shadow" style="--sqc-from: #ec4899; --sqc-to: #f43f5e;">
      <div class="squircle-card"><span class="sq-icon">&#9829;</span>Health</div>
    </div>
    <div class="squircle-card-shadow" style="--sqc-from: #06b6d4; --sqc-to: #3b82f6;">
      <div class="squircle-card"><span class="sq-icon">&#9733;</span>Photos</div>
    </div>
  </div>
CSS
/* 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;
}
JavaScript (fx-0333)

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
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.

FAQ

How is it different from a 30% border-radius?

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.

Why do the .squircle-card:nth-child(2) and (3) rules change nothing?

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.

Do I need to add an SVG clipPath to get the shape?

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.