Re: [csswg-drafts] [css-borders-4][css-shapes-1]The `round` algorithm is not continuous (#13914)

Hm, I suppose you're right. It means custom machinery for this rather than reusing SVG machinery, but I suppose I don't know to what extent we *do* reuse that machinery actually. And `path()` doesn't have the rounded-corner functionality, so at least we don't have to solve the general case; these are all sharp lines meeting at a corner.

Okay, so the competing constraints we did border-radius under are:

* in general, the inner corner reduces its radius by the spread, and the outer increases its radius by the spread
* except 0px radius needs to stay 0px when it expands, so we do a cubic interpolation between "stays the same" and "expands by the spread" based on the ratio of radius to border width; if the radius is larger than the border width (ratio > 1), it expands fully; if it's smaller, it expands less until it hits 0.
* except a *full radius* (creating a circle or ellipse) should stay properly round (expanding the radius by the spread) regardless of the radius/border-width ratio, so we do a cubic interpolation between "apply the previous bullet point" and "ignore the previous bullet point" based on the ratio of radius to *box width/height*; if the radius is at least half the box's width or height (2*ratio > 1), it's fully ignored; if smaller, it applies the previous bullet point's correction in a scaling fashion.

Here we have a general polygon. We use the border-width as the stroke width, meaning it both expands and contracts at each corner.  This is already a break from border-radius behavior: a 1px border-radius with a 20px border width will have curve radiuses of 1px inner and 21px outer (curve defined for inner edge, expanded by 20px); a `round 1px` with a 2px border width will have curve radiuses of 0px inner and 11px outer (curve defined in center of border; both expanded and contracted by 10px). Do we want to change that to match perfectly? Or is it okay for that to be a little different, since if you want a border-radius rectangular border you can just *use border-radius*? (I lean toward the latter, so all the shapes work exactly the same, matching their equivalent polygon.)

Going past the rect/inset/xywh functions, we calculate the rounding by positioning a circle of the given radius so that it's tangent to both line segments (possibly shrinking it if this would be more than half a segment's length). We then define the stroked path outlines by expanding and contracting the radius by half the border-width for the outer/inner edges of the corner, but also want the radius to stay 0 if it started as 0.

Applying the first correction, to smoothly cubic-interpolate between "add the spread" and "do nothing", seems like a no-brainer. The only question would be whether it's better to compare the radius to the full border-width, or half the border-width (the actual spread amount); I somewhat lean toward the first one to match how 'border-radius' kicks in.

The second correction is meant to handle people using border-radius to create circles/ellipses, which inclines me to say "just use `circle()`, that works correctly already", but it *also* works for *pill* shapes (full-face semicircular caps on a rectangle), which are definitely rounded rects with our current primitives. So I guess we do still need to do the same correction, and make it relative to how 2*radius compares with half the smaller segment length.

-----------

So, my initial conclusion:

When determining the outer curve of a rect/polygon corner, expand the calculated radius by:
```
(border-width/2) * (1 - (1 - ratio)³ * (1 - coverage³))
// note the differing placements of the ³ operators
```

where `ratio` is `radius / border-width` and coverage is `2 * radius / shorter-segment-length`; if either `ratio` or `coverage` is > 1, just use expand the radius by the full `border-width/2` as normal.

The inner curve always contracts the radius by the `border-width/2`, floored at 0.

-- 
GitHub Notification of comment by tabatkins
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/13914#issuecomment-4464255320 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Friday, 15 May 2026 22:57:38 UTC