Skip to content

[css-borders-4] Resolve on range for superellipse parameters #11609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
noamr opened this issue Jan 30, 2025 · 11 comments · May be fixed by #12033
Open

[css-borders-4] Resolve on range for superellipse parameters #11609

noamr opened this issue Jan 30, 2025 · 11 comments · May be fixed by #12033

Comments

@noamr
Copy link
Collaborator

noamr commented Jan 30, 2025

Follow up on #10993

The initial draft for corner-shape and superellipse uses the following parameters:

  • 0 is notch
  • 0.5 is scoop
  • 1 is bevel
  • 2 is circle
  • 4 is squircle
  • 1 is straight

We can also use the log2 version of this:
notch -> -inf
scoop -> -1
bevel -> 0
round -> 1
squircle -> 2
straight -> inf

This would have an effect on the formula in #11608 as well.

@smfr
Copy link
Contributor

smfr commented Jan 30, 2025

inf values concern me because they aren't good endpoints for interpolation.

@smfr
Copy link
Contributor

smfr commented Jan 30, 2025

Actually, that makes me wonder if we need more detail on how the superellipse is computed, given a corner size (in pixels). It would be weird for a corner to appear sharp on a small box, but still slightly rounded on a large box because of how the math works out. We need math that is size-independent.

@noamr
Copy link
Collaborator Author

noamr commented Jan 30, 2025

inf values concern me because they aren't good endpoints for interpolation.

This is addressed in the draft

@noamr
Copy link
Collaborator Author

noamr commented Jan 30, 2025

Actually, that makes me wonder if we need more detail on how the superellipse is computed, given a corner size (in pixels). It would be weird for a corner to appear sharp on a small box, but still slightly rounded on a large box because of how the math works out. We need math that is size-independent.

You mean when we describe it as bezier curves? For the cartesian equation this shouldn't matter.

@tabatkins
Copy link
Member

I strongly prefer the log2-scaled version of the superellipse parameter, so the symmetric inny and outy shapes use the same parameters, just negated; in general, it makes the "stuff poking out more than angle" and "stuff poking in more than angle" have the same value range and same value meaning, which is a lot easier to understand and use imo.

It also happens to make the most significant values even simpler - 0, 1, 2, inf.

Actually, that makes me wonder if we need more detail on how the superellipse is computed, given a corner size (in pixels). It would be weird for a corner to appear sharp on a small box, but still slightly rounded on a large box because of how the math works out. We need math that is size-independent.

You get a (mathematically) sharp corner at infinity and -infinity (or infinity and 0, in the current spec). And that's stable regardless of box size. Any value short of those endpoints will produce a curve with some extremely high curvature, so at a sufficiently large border-radius it will indeed appear curved rather than sharp.

@noamr
Copy link
Collaborator Author

noamr commented Jan 30, 2025

I strongly prefer the log2-scaled version of the superellipse parameter, so the symmetric inny and outy shapes use the same parameters, just negated; in general, it makes the "stuff poking out more than angle" and "stuff poking in more than angle" have the same value range and same value meaning, which is a lot easier to understand and use imo.

Thanks! I tend to agree.

@noamr
Copy link
Collaborator Author

noamr commented Jan 30, 2025

@smfr with my proposed formula for interpolation applied on these values it would look like this:

Name superellipse() value 0..1 value for interpolation
notch -Infinity 0
scoop -1 0.25
bevel 0 0.5
round 1 0.7
squircle 2 0.84
straight Infinity 1

The formula is intersecting the diagonal with the superellipse function, which resolves to this (given n as the arg):

// -Infinity => 0, Infinity -> 1, everything else given `n` as the `superellipse()` arg:
0.5^(1 / (2^n))
  • there could be a way to simplify this formula further, my logarithmic math is rusty

@noamr
Copy link
Collaborator Author

noamr commented Jan 31, 2025

An advantage for using the current spec'ed version (without log2) is that it's the commonly used exponent value for superellipse. So if designers say "this is a superellipse with k=5" you don't need to remember that in CSS this would be log2(5).

@smfr
Copy link
Contributor

smfr commented Mar 30, 2025

The spec needs to say how to map the 0-1 range to a k value, so you need to describe the inverse of 0.5^(1 / (2^n)), which is an ugly thing with lots of nested ln(); in JS;

            const log2 = Math.log(2);
            return (Math.log(- 1 / Math.log(fraction)) + Math.log(log2)) / log2;

And this is actually mapping p -> s, not p -> k.

I think the animation logic also needs to preserve symmetry by saying that if the fraction p < 0.5, you compute for 1-p and negate the result (or somehow otherwise agree with the spec text about how to render the curve).

@noamr
Copy link
Collaborator Author

noamr commented Mar 31, 2025

The spec needs to say how to map the 0-1 range to a k value, so you need to describe the inverse of 0.5^(1 / (2^n)), which is an ugly thing with lots of nested ln(); in JS;

            const log2 = Math.log(2);
            return (Math.log(- 1 / Math.log(fraction)) + Math.log(log2)) / log2;

And this is actually mapping p -> s, not p -> k.

Sure, the spec currently specifies this for the regular k, it's not too difficult to add the log(2) bit.
Something along the lines of this in JS:

function s_for_v(v) {
    const is_concave = v < 0.5;
    const k = ln(0.5) / ln(is_concave ? 1 - v : v);
    const s = Math.log2(k);
    return is_concave ? -s : s;
}

I think the animation logic also needs to preserve symmetry by saying that if the fraction p < 0.5, you compute for 1-p and negate the result (or somehow otherwise agree with the spec text about how to render the curve).

Agreed about symmetry.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-borders-4] Resolve on range for `superellipse` parameters, and agreed to the following:

  • RESOLVED: Use the log2 range for the superellipse parameter
The full IRC log of that discussion <TabAtkins> noamr: this and the next issue will resolve togheter
<TabAtkins> noamr: smfr and i have been working hard on the details for corner-shape. several questions to resolve
<TabAtkins> noamr: one is about the superellipse paramter
<TabAtkins> noamr: as you might recall, we have corner-shape keywords, but can also give it a number via a super-ellipse function
<TabAtkins> noamr: in the spec righ tnow, the number gives the exponent of the curvature
<TabAtkins> noamr: there was a proposal to use the log2 of that
<TabAtkins> noamr: if i go all the way to concave, k=0, log2=-inf
<TabAtkins> noamr: middle, bevel, k=1, log2=0
<TabAtkins> noamr: full sharp convex, k=inf, log=inf
<TabAtkins> noamr: round, k=2, log2=1
<TabAtkins> noamr: squircle, k=4, log2=2
<TabAtkins> noamr: there's a table in the issue
<TabAtkins> noamr: so the log2 version goes from -inf to inf, and maybe a bit more friendly
<TabAtkins> noamr: k version goes 0-inf
<astearns> https://noamr.github.io/squircle-testbed/corner-visualizer/corner-animation.html
<TabAtkins> noamr: advantage of k version, when people talk about super-ellipses in other contexts they're usually talking just about the k version
<TabAtkins> noamr: but i don't feel strongly about either
<TabAtkins> q+
<astearns> ack TabAtkins
<fantasai> TabAtkins: I do feel strongly that the log2 version is better here, because the shapes are symmetrical across the bevel
<fantasai> TabAtkins: It also makes the range of useful values more reasonable. Going out to log2=10 makes it effectively a sharp corner, and the range past there is infinite
<fantasai> TabAtkins: Same thing applies in negative direction.
<fantasai> TabAtkins: This is easy to work with.
<fantasai> TabAtkins: in the straight K version, sharp corner is a non-obvious fraction slightly above zero...
<fantasai> TabAtkins: Symmetry really helps out with usability. Can put a note in the spec that k in academic papers is usually different, but for authors they won't care. We should prioritize usability for authors, and log2 variant gets us there
<TabAtkins> fantasai: +1
<bramus> +1
<TabAtkins> noamr: literature could be Figma, for example
<TabAtkins> noamr: author tooling can expose it too
<Kurt> q+
<astearns> ack Kurt
<TabAtkins> Kurt: does this mean specifcying infinity you need to use calc()?
<TabAtkins> noamr: no, can just have an infinity keyword
<TabAtkins> noamr: that's in the spec right now for positive infinity
<TabAtkins> noamr: i think people are okay with this not aligning with other tools i'm okay with going with log2
<TabAtkins> s/think people/think if people/
<TabAtkins> astearns: so it sounds like proposed is to use log2 range?
<TabAtkins> jensimmons: would like to know what smfr thinks?
<TabAtkins> noamr: he's commented on the issues, he doesn't have a strong opinion
<TabAtkins> q+
<fantasai> TabAtkins: There's an interpolation issue later on...
<lea> weak agree for the log2 version from me too
<fantasai> TabAtkins: Other reason I really like log2, when we do interpolation, making sure that works symmetrically requires doing log2 anyway
<fantasai> TabAtkins: so exposing more directly to authors is a good thing
<TabAtkins> noamr: yeah, the interpolation function si clsoe to log2
<TabAtkins> astearns: so it sounds like people are moderate to weakly in favor of log2
<TabAtkins> fantasai: i think tab's arguments are convincing to me
<TabAtkins> astearns: so proposed reoslution is to use the log2 range
<TabAtkins> RESOLVED: Use the log2 range for the superellipse parameter

noamr added a commit to noamr/csswg-drafts that referenced this issue Apr 1, 2025
- Use `square` instead of `straight`
- Use the log2 version for the `superellipse()` parameter
- Interpolate symetrically from the middle.

Closes w3c#11607
Closes w3c#11608
Closes w3c#11609
@noamr noamr linked a pull request Apr 1, 2025 that will close this issue
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Apr 3, 2025
The number for the CSS exposed superellipse() function
should be the log2(k) where k is the curvature exponent.

Changed all the tests to take that into account.
Applied the fix only in the CSS layer, where the value is
converted to the curvature exponent when creating the
ContouredRect for painting.

See CSSWG resolution:
w3c/csswg-drafts#11609 (comment)

R=fs@opera.com

Fixed: 407749391
Bug: 407749391
Change-Id: I0abb08eede485153782176c9e75888f82aae1727
aarongable pushed a commit to chromium/chromium that referenced this issue Apr 3, 2025
The number for the CSS exposed superellipse() function
should be the log2(k) where k is the curvature exponent.

Changed all the tests to take that into account.
Applied the fix only in the CSS layer, where the value is
converted to the curvature exponent when creating the
ContouredRect for painting.

See CSSWG resolution:
w3c/csswg-drafts#11609 (comment)

R=fs@opera.com

Fixed: 407749391
Bug: 407749391
Change-Id: I0abb08eede485153782176c9e75888f82aae1727
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6425306
Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org>
Reviewed-by: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/main@{#1442020}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Apr 3, 2025
The number for the CSS exposed superellipse() function
should be the log2(k) where k is the curvature exponent.

Changed all the tests to take that into account.
Applied the fix only in the CSS layer, where the value is
converted to the curvature exponent when creating the
ContouredRect for painting.

See CSSWG resolution:
w3c/csswg-drafts#11609 (comment)

R=fs@opera.com

Fixed: 407749391
Bug: 407749391
Change-Id: I0abb08eede485153782176c9e75888f82aae1727
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6425306
Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org>
Reviewed-by: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/main@{#1442020}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Apr 3, 2025
The number for the CSS exposed superellipse() function
should be the log2(k) where k is the curvature exponent.

Changed all the tests to take that into account.
Applied the fix only in the CSS layer, where the value is
converted to the curvature exponent when creating the
ContouredRect for painting.

See CSSWG resolution:
w3c/csswg-drafts#11609 (comment)

R=fs@opera.com

Fixed: 407749391
Bug: 407749391
Change-Id: I0abb08eede485153782176c9e75888f82aae1727
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6425306
Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org>
Reviewed-by: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/main@{#1442020}
ChunMinChang pushed a commit to ChunMinChang/gecko-dev that referenced this issue Apr 7, 2025
…perellipse, a=testonly

Automatic update from web-platform-tests
corner-shape: use the log2 variant of superellipse

The number for the CSS exposed superellipse() function
should be the log2(k) where k is the curvature exponent.

Changed all the tests to take that into account.
Applied the fix only in the CSS layer, where the value is
converted to the curvature exponent when creating the
ContouredRect for painting.

See CSSWG resolution:
w3c/csswg-drafts#11609 (comment)

R=fs@opera.com

Fixed: 407749391
Bug: 407749391
Change-Id: I0abb08eede485153782176c9e75888f82aae1727
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6425306
Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org>
Reviewed-by: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/main@{#1442020}

--

wpt-commits: ea49709e5880c8133249d919c72d67798afc31ec
wpt-pr: 51823
i3roly pushed a commit to i3roly/firefox-dynasty that referenced this issue Apr 8, 2025
…perellipse, a=testonly

Automatic update from web-platform-tests
corner-shape: use the log2 variant of superellipse

The number for the CSS exposed superellipse() function
should be the log2(k) where k is the curvature exponent.

Changed all the tests to take that into account.
Applied the fix only in the CSS layer, where the value is
converted to the curvature exponent when creating the
ContouredRect for painting.

See CSSWG resolution:
w3c/csswg-drafts#11609 (comment)

R=fs@opera.com

Fixed: 407749391
Bug: 407749391
Change-Id: I0abb08eede485153782176c9e75888f82aae1727
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6425306
Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org>
Reviewed-by: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/main@{#1442020}

--

wpt-commits: ea49709e5880c8133249d919c72d67798afc31ec
wpt-pr: 51823
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this issue Apr 8, 2025
…perellipse, a=testonly

Automatic update from web-platform-tests
corner-shape: use the log2 variant of superellipse

The number for the CSS exposed superellipse() function
should be the log2(k) where k is the curvature exponent.

Changed all the tests to take that into account.
Applied the fix only in the CSS layer, where the value is
converted to the curvature exponent when creating the
ContouredRect for painting.

See CSSWG resolution:
w3c/csswg-drafts#11609 (comment)

R=fsopera.com

Fixed: 407749391
Bug: 407749391
Change-Id: I0abb08eede485153782176c9e75888f82aae1727
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6425306
Commit-Queue: Noam Rosenthal <nrosenthalchromium.org>
Reviewed-by: Fredrik Söderquist <fsopera.com>
Cr-Commit-Position: refs/heads/main{#1442020}

--

wpt-commits: ea49709e5880c8133249d919c72d67798afc31ec
wpt-pr: 51823

UltraBlame original commit: b71898345a83581a976c59bff18b4182b7185f91
globau pushed a commit to globau/firefox-test that referenced this issue Apr 8, 2025
…perellipse, a=testonly

Automatic update from web-platform-tests
corner-shape: use the log2 variant of superellipse

The number for the CSS exposed superellipse() function
should be the log2(k) where k is the curvature exponent.

Changed all the tests to take that into account.
Applied the fix only in the CSS layer, where the value is
converted to the curvature exponent when creating the
ContouredRect for painting.

See CSSWG resolution:
w3c/csswg-drafts#11609 (comment)

R=fs@opera.com

Fixed: 407749391
Bug: 407749391
Change-Id: I0abb08eede485153782176c9e75888f82aae1727
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6425306
Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org>
Reviewed-by: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/main@{#1442020}

--

wpt-commits: ea49709e5880c8133249d919c72d67798afc31ec
wpt-pr: 51823
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this issue Apr 8, 2025
…perellipse, a=testonly

Automatic update from web-platform-tests
corner-shape: use the log2 variant of superellipse

The number for the CSS exposed superellipse() function
should be the log2(k) where k is the curvature exponent.

Changed all the tests to take that into account.
Applied the fix only in the CSS layer, where the value is
converted to the curvature exponent when creating the
ContouredRect for painting.

See CSSWG resolution:
w3c/csswg-drafts#11609 (comment)

R=fsopera.com

Fixed: 407749391
Bug: 407749391
Change-Id: I0abb08eede485153782176c9e75888f82aae1727
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6425306
Commit-Queue: Noam Rosenthal <nrosenthalchromium.org>
Reviewed-by: Fredrik Söderquist <fsopera.com>
Cr-Commit-Position: refs/heads/main{#1442020}

--

wpt-commits: ea49709e5880c8133249d919c72d67798afc31ec
wpt-pr: 51823

UltraBlame original commit: b71898345a83581a976c59bff18b4182b7185f91
gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this issue Apr 8, 2025
…perellipse, a=testonly

Automatic update from web-platform-tests
corner-shape: use the log2 variant of superellipse

The number for the CSS exposed superellipse() function
should be the log2(k) where k is the curvature exponent.

Changed all the tests to take that into account.
Applied the fix only in the CSS layer, where the value is
converted to the curvature exponent when creating the
ContouredRect for painting.

See CSSWG resolution:
w3c/csswg-drafts#11609 (comment)

R=fsopera.com

Fixed: 407749391
Bug: 407749391
Change-Id: I0abb08eede485153782176c9e75888f82aae1727
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6425306
Commit-Queue: Noam Rosenthal <nrosenthalchromium.org>
Reviewed-by: Fredrik Söderquist <fsopera.com>
Cr-Commit-Position: refs/heads/main{#1442020}

--

wpt-commits: ea49709e5880c8133249d919c72d67798afc31ec
wpt-pr: 51823

UltraBlame original commit: b71898345a83581a976c59bff18b4182b7185f91
jamienicol pushed a commit to jamienicol/gecko that referenced this issue Apr 9, 2025
…perellipse, a=testonly

Automatic update from web-platform-tests
corner-shape: use the log2 variant of superellipse

The number for the CSS exposed superellipse() function
should be the log2(k) where k is the curvature exponent.

Changed all the tests to take that into account.
Applied the fix only in the CSS layer, where the value is
converted to the curvature exponent when creating the
ContouredRect for painting.

See CSSWG resolution:
w3c/csswg-drafts#11609 (comment)

R=fs@opera.com

Fixed: 407749391
Bug: 407749391
Change-Id: I0abb08eede485153782176c9e75888f82aae1727
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6425306
Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org>
Reviewed-by: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/main@{#1442020}

--

wpt-commits: ea49709e5880c8133249d919c72d67798afc31ec
wpt-pr: 51823
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Tuesday Morning
Development

Successfully merging a pull request may close this issue.

4 participants