· 2 min read ·

What It Actually Takes to Ship CSS corner-shape

Source: chrome-devblog

CSS has always been deceptively simple at the surface. border-radius feels obvious — you set a value, corners get round. But when the Chrome team sat down to implement corner-shape in Blink, they ran straight into the kind of edge cases that remind you how much hidden complexity lives underneath every CSS property.

corner-shape is part of the CSS Borders Level 4 spec. It lets you go beyond round corners and into a whole taxonomy of shapes: bevel, notch, scoop, squircle, angle. The goal is giving designers control over corner geometry that today requires SVG clip-paths or Canvas hacks. That’s genuinely useful. But the gap between “define a shape” and “render it correctly in every layout context” turns out to be substantial.

The Geometry Problem

With border-radius, each corner is a quarter-ellipse. The math is well-understood, the interpolation is straightforward, and edge cases are manageable. With corner-shape, you’re dealing with parametric curves that vary per shape type. A squircle corner, for instance, follows a superellipse formula — |x/a|^n + |y/b|^n = 1 — where n controls how “square” the curve feels. That sounds fine until you have to:

  • Resolve percentages relative to the element’s computed dimensions
  • Handle corners that would overlap (the same budget-sharing logic border-radius uses, but now applied to non-elliptical curves)
  • Composite correctly when border-image, outline, and box-shadow are all in play
  • Clip child content to the shaped boundary

The overlap resolution issue is particularly interesting. When an element is small enough that two adjacent corners would collide, browsers scale both down proportionally. Implementing that same logic for arbitrary corner shapes means computing intersection points on curves that don’t have closed-form solutions for all shape types.

Where Animation Gets Messy

Interpolating between corner-shape values adds another layer. Animating round to bevel isn’t a single numeric lerp — you’re blending between fundamentally different curve types. The spec has to define what that transition looks like, and the implementation has to produce smooth, artifact-free output at every frame. Doing that without per-frame recalculations eating into rendering performance requires careful caching of intermediate geometry.

Why It Matters

Shipping this properly is worth the effort. The current workarounds — clip-path: polygon() for bevel, SVG masks for notch effects, JS-calculated squircle paths — are all fragile. They break with dynamic sizing, they don’t respect border or padding, and they’re invisible to hit-testing and accessibility trees.

Native corner-shape fixes all of that. Once it’s in Blink, corners become first-class layout citizens, composited and clipped correctly by the same infrastructure that handles everything else.

The Chrome team’s writeup is a good reminder that browser engineering isn’t just about following a spec — it’s about anticipating every interaction between a new feature and the ten thousand other things the engine already does. The corner cases, in this case, are quite literally the point.

Was this interesting?