This note has an interactive demo. Try it in the original
Since it arrived, border-radius has given us exactly one kind of corner: a quarter of an ellipse. corner-shape changes that. You keep border-radius for the size of the corner and add one property for its shape: squircle, bevel, scoop, notch, or anything in between. Borders, outlines and shadows follow the new outline, and the browser can animate from one shape to another.
Play with the demo above first. Press the chips, drag the K slider, then hit "Morph between shapes". Watch the teal border and the glow: they're not a separate layer, they bend with the box.
Size from border-radius, shape from corner-shape
The property doesn't replace border-radius, it builds on it. MDN puts it plainly: "If a border-radius is not applied to a container, or the border-radius resolves to 0, corner-shape will have no effect."
.card {
border-radius: 56px; /* how big the corner is */
corner-shape: scoop; /* what the corner looks like */
}
That's the whole of the demo's main shape. The keywords are:
-
square=superellipse(infinity): a normal square corner. -
squircle=superellipse(2): between round and square, the app-icon look. -
round=superellipse(1): today'sborder-radius, and the initial value. -
bevel=superellipse(0): a straight diagonal cut. -
scoop=superellipse(-1): a concave quarter circle bitten out. -
notch=superellipse(-infinity): a concave 90° step.
Because the initial value is round, adding corner-shape to an existing design changes nothing until you pick another shape.
What superellipse(K) really means
Every keyword is a point on one continuous scale. The spec defines superellipse(K) as a quarter of a superellipse "using an exponent of 2^K". A superellipse is the curve |x|^n + |y|^n = 1:
- With K = 1, n = 2 and you get a circle:
round. - With K = 2, n = 4: the flatter-sided
squircle. - With K = 0, n = 1: a straight line,
bevel. - Negative K mirrors the curve inwards, so
superellipse(-1)is a concave circle,scoop.
That's what the small corner plot in the demo draws. It's the same formula I use in the fallback (more on that below): each corner is sampled from the parametric superellipse x = cos(t)^(2/n), y = sin(t)^(2/n) and mirrored inwards when K is negative.
You can also mix shapes per corner, with the same clockwise order as border-radius (top-left, top-right, bottom-right, bottom-left):
.launch {
border-radius: 14px 0; /* only top-left and bottom-right */
corner-shape: notch;
}
.tag {
border-radius: 0 32px 32px 0;
corner-shape: bevel; /* the right side becomes an arrow */
}
Those are two of the four small pieces at the bottom of the demo. There are longhands too: corner-top-left-shape, logical ones like corner-start-start-shape, and per-side shorthands like corner-top-shape.
Borders, shadows and animation come with it
This is what makes it more than a clip-path trick. According to MDN, background, border, outline, box-shadow, overflow and backdrop-filter all follow the corner shape. A clip-path just cuts pixels away, so a border gets sliced and a shadow disappears.
There's one nuance in the spec: the inner edge of the border follows the outer curve at a nearly constant distance, but box-shadow doesn't trace the path exactly. It "scales the corner-shape path in an axis-aligned manner". With big spreads you may see a small difference.
It also animates:
.card {
transition: corner-shape .9s cubic-bezier(.3, .8, .2, 1);
}
The browser interpolates the K parameter, not the keyword. The spec doesn't move K linearly, though. Going from bevel (0) to round (1) to square (infinity) linearly would start fast and crawl at the end, so the spec maps K onto a 0–1 scale first. I checked it in Chromium: 400 ms into a one-second linear transition from round to notch, getComputedStyle reports superellipse(-0.327908), a real in-between shape rather than a jump.
Browser support and gotchas
-
Only Chromium so far. The Chrome 139 release notes list "Corner shaping (
corner-shape,superellipse,squircle)", and webstatus.dev shows it in Chrome and Edge since August 2025. Firefox and Safari don't have it yet, so it's far from Baseline. -
The fallback is free if round is acceptable. In a browser without support,
corner-shapeis ignored andborder-radiusstill draws round corners. For a squircle button that's a perfectly fine degradation. -
Concave shapes need a plan B. If your design depends on a scoop or notch (a ticket, a sci-fi frame), round corners aren't the same thing. Detect support with
@supports (corner-shape: squircle)orCSS.supports('corner-shape', 'squircle'). The demo then computes the same superellipse as aclip-path: polygon()and shows a notice. It's honest about the trade-off: in Firefox and Safari the shape is right, but the border and shadow no longer follow it, so the demo swaps the shadow for adrop-shadow()filter on a wrapper. - Opposite corners can collide. With large radii and concave shapes, MDN notes that "the browser constrains the values to prevent the overlap", so the result may be smaller than what you asked for.
- Content isn't reshaped. Text and hover areas still belong to the rectangular box. Leave padding near notched or scooped corners.
What to keep an eye on
- Whether Firefox and Safari pick up
corner-shape. Until they do, use it as an enhancement on top ofborder-radius. - The rest of CSS Borders Level 4, where this lives. It's an Editor's Draft that also covers
border-shapeand partial borders, so details may still change. - Design tools exporting squircles. Since
superellipse()takes any number, a design system can now name its exact corner curve in CSS instead of shipping an SVG mask.
Sources
- corner-shape - CSS | MDN
- CSS Borders and Box Decorations Module Level 4 (Editor's Draft)
- Chrome 139 release notes | Chrome for Developers
- corner-shape | Web Platform Status
Originally published at richi.codes.
Top comments (0)