A box with superellipse corners: native CSS corner-shape where the browser has it, an identical clip-path everywhere else.
Motion signature: scrub the superellipse exponent from 1 (round) through 2 (squircle) toward square and the corners morph continuously, with a dashed round outline showing exactly how much further into the corner the curve reaches; the native and clip-path renderings draw the same curve.
Usage
import { Squircle } from "@/components/eased/squircle/squircle";
<Squircle radius={36} exponent={2} ring className="size-32 bg-surface-raised">
…
</Squircle>Where CSS.supports("corner-shape", "superellipse(2)") (Chromium 139+), it renders border-radius plus corner-shape: superellipse(K), so borders, shadows and the ring hairline follow the curve. Elsewhere it measures itself with a ResizeObserver and clips to the same curve with clip-path: path(), drawing the hairline as an SVG stroke. The server and first client render assume native support, so unsupported browsers show round corners for one frame, never square ones. A clip cannot keep outer shadows or borders: in fallback put them on a wrapper (filter: drop-shadow follows the clip) or use ring.
Use it on radii of 16px and up (R7): app icons, avatars, large cards and media. Never on controls.
Props
| Prop | Default | |
|---|---|---|
radius | 24 | Corner radius, px. Shrinks past half the shorter side, like border-radius. |
exponent | 2 | K in superellipse(K): 0 bevel, 1 round, 2 squircle, higher is squarer (the fallback clamps to 0–8). |
mode | "auto" | "native" or "fallback" to force one. |
ring | false | 1px image-ring hairline that follows the shape. |
| …div props | className, style, events, ARIA. Exposes data-squircle="native" or "clip-path". |
Also exported: superellipsePath(width, height, radius, exponent) (the outline as a path string, for SVG or CSS) and useCornerShapeSupport().
Nothing animates by itself, so there is no reduced-motion branch; the shape follows its props.