Skip to content
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

[css-values] Function(s) for Standard Means #4700

Closed
Crissov opened this issue Jan 24, 2020 · 8 comments
Closed

[css-values] Function(s) for Standard Means #4700

Crissov opened this issue Jan 24, 2020 · 8 comments

Comments

@Crissov
Copy link
Contributor

Crissov commented Jan 24, 2020

ECMA-262 (Javascript) does not have dedicated functions (in its global Math object #4688) for the commonly known standard means, except for a rather unexpected one:

  • arithmetic mean or average or middle: calc( (x + y) / 2), calc( (x + y + ) / 3)
  • geometric mean or arithmetic-harmonic mean: sqrt(x * y), pow(x * y * z, 1/3)
  • harmonic mean: calc(2 / (1/x + 1/y) ), calc(3 / (1/x + 1/y + 1/z) )
  • quadratic mean or root mean square (RMS): sqrt( (x*x + y*y) / 2), hypot(x, y, z)
  • cubic mean: cbrt( (x*x*x + y*y*y) / 2) (if it was added), pow( (pow(x, 3) + pow(y, 3) + pow(z, 3)) / 3, 1/3)

Those can all be described by a generalized mean or power mean by a characteristic integer exponent i: pow( (pow(x, i) + pow(y, i)) / 2, 1/i), pow( (pow(x, i) + pow(y, i) + pow(z, i)) / 3, 1/i). This exponent is −1 for the harmonic, 0 for the geometric, 1 for the arithmetic, 2 for the quadratic and 3 for the cubic mean (and so on).

There are two lesser known means, usually specified only for two arguments, i.e. the arithmetic-geometric mean and the geometric-harmonic mean, which result from letting i be ±½.

The code example provided above use two or three arguments, but for an arbitrary number of arguments, one would need functions like sum() or add() for Σ, product() or multiply() for Π and count() or n() to calculate these means. This would be simple to do in JS, but is hard – probably impossible – in plain CSS.

In #581, a map() or interpolate() function has been proposed, which would be related to these functions. (The resolution of that issue is in #2854 with specification pending.) Unfortunately – and almost as usual – I cannot provide any specific use cases for such mean functions, but I think they might be valuable in working with colors, positions and transitions as well as sets of sizes, especially when using cascading variables and units that may compute to different values depending on the user's environment. The steps of font-size keywords, for instance, should form a geometric progression, i.e. a new step between two existing sizes would be calculated as the geometric mean thereof (which is possible already, now that sqrt() or pow() exists).

In case there was agreement to add functions to calculate standard means to CSS, there would still be the issue whether to do so in a single function mean(..., i) (iN, i ≥ −1; or i ∈ {h | g | a | q | c}; or i ∈ {harmonic | geometric | arithmetic | quadratic | cubic}) or in several separate functions like avg(), average(), mid(), middle(), medium() or amean(), meana(), mean-a(), arithmetic-mean(), mean-arithmetic(), mean1() and so on.

PS: For a proposal for mode mod()mode() and median med() see #905.

@Crissov
Copy link
Contributor Author

Crissov commented Jan 24, 2020

PS: Such high-level functions have an advantage over multiplication, division, power and root functions in that they do not need to worry as much about keeping units consistent. The result is always of the same dimension as all of the input arguments. I believe this is a sufficient argument against requiring authors to calculate these means themselves, if their overall use case was accepted.

@tabatkins
Copy link
Member

Since there are no datastructures containing arbitrary numbers of values in CSS, there's no need for an explicit sum/product/count/etc, you can just list out the additions/multiplications yourself and count the values.

If use-cases were provided for some of these means, I think they're reasonable additions, for the unit-simplicity reasons you mentioned.

@Crissov
Copy link
Contributor Author

Crissov commented Jan 26, 2020

Iʼm no expert in CSS variables by any means, but as far as I understand them, they can hold a number of values (separated by whitespace or commas) that could be passed into a function all at once, but Iʼm not sure whether anyone is doing that or why they would.

foo {
  --lengths: 1.2em, 34pt, 56px, 78%, 9.0mm; /* 9mm < 34pt < 56px */
  font-size: min(var(--lengths)); /* min(1.2em, 78%, 9mm) */
  line-height: max(var(--lengths)); /* max(1.2em, 78%, 56px) */
  padding-top: mean(var(--lengths));
} 
bar {
  --trouble: 1em 1em 2em 2em;
  margin: var(--trouble);
  border: solid red mean(var(--trouble)); /* 1.5em */
  padding: calc(each(var(--trouble)) * 0.2); /* 0.2em 0.2em 0.4em 0.4em */
  text-decoration-width: calc(index(var(--trouble), 3) / 4); /* 0.5em */
} 

each and index are examples of other functions that would be useful when working with sets of values of equal type.

@tabatkins
Copy link
Member

Right, I'm not sure why anyone would do those things. ^_^

@Crissov
Copy link
Contributor Author

Crissov commented Jan 27, 2020

Regardless of the actual proposal, this raises the question, whether var() should be able to split multiple values and simulate the appropriate separator when used in a property or function that accepts an arbitrary number of arguments, or whether such functions should be able to deal with such input themselves, like rgb() mostly does but for legacy reasons.

I believe itʼs not crazy wanting to use min() or max() with a space-separated <position>, for instance, expecting to get exactly 1 length out of up to 4.

@Crissov
Copy link
Contributor Author

Crissov commented Feb 4, 2020

Just for the record, there is another kind of mean that is relevant in color space transformation, for instance:

  • mid-range: (min(x, …, y) + max(x, …, y)) / 2
  • range: max(x, …, y) - min(x, …, y)

@fantasai
Copy link
Collaborator

Closed for lack of meaningful use cases.

@Crissov
Copy link
Contributor Author

Crissov commented Nov 30, 2023

For an equivalent replacement of mix() for simple values, we would need weighted means to be able to represent <progress> other than 50%.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants