Docs: hyperellipse.vercel.app
A transparent polyfill for CSS corner-shape β squircles, superellipses, scoops, notches, and per-corner mixes.
Native rendering where the browser already supports corner-shape. A spec-accurate JS fallback everywhere else (Safari, Firefox).
.card {
--corner-shape: squircle;
border-radius: calc(24px * var(--corner-scale, 1));
background: #4f46e5;
}import { registerHyperellipse } from "hyperellipse";
registerHyperellipse();- Progressive β supporting browsers get a tiny zero-specificity CSS bridge; no observers, no layout work in JS
- Spec-aligned geometry β superellipse math from CSS Borders 4, so Chrome and the fallback match
- Real-world CSS β backgrounds, gradients, borders,
box-shadow,outline+outline-offset - SSR-friendly β optional
--corner-scalesnippet removes the flash of overly round corners before hydration - Tiny API β one
registerHyperellipse()call; idempotent and SSR-safe
npm install hyperellipse
# bun add hyperellipse
# pnpm add hyperellipse1. Style elements with a custom property carrier
Browsers without corner-shape drop the native property at parse time. --corner-shape survives in the CSSOM and drives both native and fallback paths:
.button {
--corner-shape: squircle;
border-radius: 45px;
background: #2563eb;
}You can also set the native property for zero-JS Chrome:
.button {
corner-shape: squircle;
--corner-shape: squircle;
border-radius: 45px;
}2. Register once on the client
import { registerHyperellipse } from "hyperellipse";
registerHyperellipse();3. (Recommended) Add the SSR radius snippet
Squircles look less round than circles at the same radius. Scale border-radius down in unsupported browsers so the first paint already feels right:
/* global.css */
@supports not (corner-shape: squircle) {
:root {
--corner-scale: 0.6;
}
}.button {
--corner-shape: squircle;
border-radius: calc(45px * var(--corner-scale, 1));
}Or import the bundled snippet:
@import "hyperellipse/css";Same shorthand grammar as native corner-shape (1β4 values):
--corner-shape: squircle;
--corner-shape: superellipse(4);
--corner-shape: squircle bevel scoop notch;Keywords: round, squircle, square, bevel, scoop, notch, superellipse(K).
Per-element without a stylesheet rule:
<div data-corner-shape="squircle" style="border-radius: 32px"></div>const controller = registerHyperellipse({
selector: ".card", // extra selectors (cross-origin sheets)
pendingRadiusScale: 0.6, // pre-hydration radius scale when JS runs
force: false, // force fallback in supporting browsers
});
controller.supported; // native corner-shape?
controller.active; // fallback engine running?
controller.refresh(); // rescan + recompute
controller.destroy(); // tear downFull API notes, rendering strategies, limitations, and performance details live in packages/hyperellipse/README.md.
| Environment | What happens |
|---|---|
Chrome / native corner-shape |
Injects corner-shape: var(--corner-shape, round) via @property bridge |
| Safari / Firefox | Scans stylesheets for --corner-shape, renders with clip-path / SVG layers |
| SSR | --corner-scale CSS snippet softens corners before JS loads |
An Agent Skill ships with this repo so coding agents integrate hyperellipse correctly (SSR snippet, API, limitations). Works with any agent on skills.sh β Cursor, Claude Code, Codex, GitHub Copilot, Windsurf, and others.
npx skills add mikhailmogilnikov/hyperellipse@hyperellipse -ySource: skills/hyperellipse/SKILL.md
cd apps/docs
bun install
bun run dev
bun run build
bun run previewMonorepo managed with Bun workspaces and Turborepo.
bun install
bun run build # build all packages
bun run dev # docs + package watch
bun run check # lint / format (ultracite)
bun run check-types # typecheckChangesets locally. Only hyperellipse is versioned and published to npm:
bun changeset # describe your change
bun version-packages # bump versions + changelog
bun release # build + publish to npmCommits follow Conventional Commits. See CONTRIBUTING.md.