How I Brought CSS corner-shape to Safari and Firefox
The new CSS corner-shape property is one of the most exciting additions to modern CSS.
It allows developers to create squircles, superellipses, scoops, notches, and other corner geometries using pure CSS:
.card {
corner-shape: squircle;
border-radius: 48px;
}
Unfortunately, there's a catch.
Today, corner-shape only works in Chromium-based browsers. Safari and Firefox ignore the property entirely and fall back to ordinary rounded corners.
As a result, the same stylesheet can produce completely different geometry depending on the browser.
Why This Matters
For years, designers have relied on SVG masks, clip-paths, custom canvas renderers, and various smoothing tricks to achieve shapes that go beyond traditional rounded rectangles.
The arrival of corner-shape finally gives us a standard CSS solution.
Instead of describing geometry through SVGs or custom rendering code, we can express it directly in CSS:
.card {
corner-shape: squircle;
border-radius: 48px;
}
The problem is browser support.
A feature that's only available in one browser is difficult to adopt in production.
Existing Approaches
Before building a polyfill, I explored several alternatives:
- SVG masks
- clip-path
- canvas rendering
- custom squircle implementations
Most of them work well for simple demos.
However, things become much more complicated when you start dealing with real UI components.
Questions quickly appear:
- What about borders?
- What about outlines?
- What about shadows?
- What about SSR?
- What about transitions?
- What about responsive layouts?
More importantly, none of these approaches actually implement the CSS specification.
They simply generate a shape that looks similar.
The Goal
I wanted developers to be able to write standard CSS and get consistent results everywhere.
.card {
corner-shape: squircle;
border-radius: 48px;
}
The desired behavior is straightforward:
- Chromium uses native rendering.
- Safari and Firefox use a fallback.
- The geometry remains consistent.
Developers shouldn't need separate implementations for different browsers.
Matching Native Geometry
This turned out to be the hardest part of the project.
Generating a squircle is relatively easy.
Generating a squircle that visually matches Chromium's implementation is much harder.
Even small geometric differences become obvious when shapes are compared side by side.
A significant portion of the work went into reproducing the geometry defined by the CSS Borders Level 4 specification and comparing the output against native browser rendering.
The goal wasn't to create a shape that looked close enough.
The goal was to create a fallback that felt indistinguishable from native rendering.
Beyond Geometry
A production-ready solution requires more than shape generation.
The implementation also needed to support:
- borders
- outlines
- shadows
- background images
- gradients
- responsive layouts
- width and height transitions
- server-side rendering
Many of these features introduce additional geometry and rendering challenges that don't appear in simple shape demos.
Native-First Architecture
One of the design goals was to avoid replacing native browser behavior.
When corner-shape is available, the browser should remain responsible for rendering.
Hyperellipse only activates in browsers that don't support the property.
The result is a native-first approach:
- Native rendering in Chromium
- Fallback rendering in Safari and Firefox
Developers continue using the same CSS API everywhere.
SSR Support
Another challenge was SSR.
Without careful handling, shapes can visibly change during hydration when JavaScript loads.
To avoid that, Hyperellipse includes an SSR-friendly strategy that minimizes visual differences before the runtime becomes active.
This allows components to remain visually stable from the first paint.
The Result
The final result is Hyperellipse, an open-source CSS corner-shape polyfill.
It brings:
- squircles
- superellipses
- scoops
- notches
- bevels
- squares
to browsers without native support while preserving native rendering where support already exists.
Example
.card {
--corner-shape: squircle;
border-radius: 48px;
}
import { registerHyperellipse } from "hyperellipse";
registerHyperellipse();
Links
Documentation:
GitHub:
mikhailmogilnikov
/
hyperellipse
CSS corner-shape polyfill — squircles, superellipses, scoops & notches
hyperellipse
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();
Features
- 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
Installation
npm install hyperellipse
# bun add hyperellipse
# pnpm add hyperellipse
I'm curious to hear feedback from anyone experimenting with corner-shape, browser rendering, or modern CSS geometry.
Top comments (0)