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] Add sign() math function #4673

Closed
Loirooriol opened this issue Jan 15, 2020 · 4 comments
Closed

[css-values] Add sign() math function #4673

Loirooriol opened this issue Jan 15, 2020 · 4 comments

Comments

@Loirooriol
Copy link
Contributor

Can we add the analogous of the ECMAScript Math.sign()? That is

  • sign(x) is 1 if x > +0
  • sign(+0) is +0
  • sign(-0) is -0
  • sign(x) is -1 if x < -0
  • sign(NaN) is NaN

For non-zero values it can be achieved with x / hypot(x) or clamp(-1, x / 0, 1), but these are NaN for zero.

I think sign() can be very useful given that CSS doesn't have conditionals (#3455).

For example:

width: calc(if (100vw > 100px) then (1em) else (1lh));

is not possible, but with sign() I could use

--cond: sign(max((100vw - 100px) / 1px, 0));
width: calc(1em * var(--cond) + 1lh * (1 - var(--cond)));

Or #2513 is discussing a round() function that rounds to the nearest, or upwards in case of tie. So round(2.5) would be 3 and round(-2.5) would be -2. But what if in case of tie I want to round towards 0, or away from zero? It's very simple with sign():

round(-hypot(x)) * sign(-x) /* round towards 0 in case of tie */
round(hypot(x)) * sign(x) /* round away from 0 in case of tie */
@Loirooriol Loirooriol added the css-values-4 Current Work label Jan 15, 2020
@AmeliaBR
Copy link
Contributor

While I have no direct objection to a sign() function, I'd much rather address your particular use cases directly, with rounding options and with conditional functions.

@Loirooriol
Copy link
Contributor Author

But conditional functions were rejected in #3455 because they are too powerful. With sign() we can have some kind of conditions but it's just arithmetic so it's fine.

And about rounding options, it was just an example, but there are many others.
For example, in case of tie maybe someone wants to choose the nearest even number, e.g. 6.5 rounds to 6 and 7.5 rounds to 8 (a bit strange but some language does this by default if I recall correctly).

So my point is that native CSS can't offer all possible behavior customizations, because there are so many options. Instead we should let authors achieve what they want with sign(), and if some behavior is very popular but not much readable with sign(), then add a nicer way in CSS.

The example could be

--is-tie: calc((1 - hypot(sign(2*x - ceil(x) - floor(x)))) * sign(ceil(x) - floor(x)));
calc(round(x/2)*2 * var(--is-tie) + round(x) * (1 - var(--is-tie)));

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed sign(), and agreed to the following:

  • RESOLVED: add the sign() function as described in the issue, restricted to numbers only
The full IRC log of that discussion <bkardell_> topic: sign()
<bkardell_> TabAtkins: this one was opened by oriol, asking for Math.sign equivalent, the usecase presented is hacky, but sure, why not - it seems unobjectionable - I'm happy to add it... he notes you can actualy implement it yourself, it is even worse
<astearns> github: https://github.com//issues/4673
<bkardell_> myles_: should the sign of 1px be....
<bkardell_> heycam: it should return a number if we allow lengths
<bkardell_> emilio: what about percentages?
<bkardell_> TabAtkins: 50% should resolve to whatever that resolves to
<bkardell_> bkardell_: in ..pixels
<bkardell_> TabAtkins: in many cases, pixels, but whatever that resolves against
<heycam> make calc(sign(1px)) == 1, because you usually use the result of sign() to multiply against other things
<bkardell_> myles: you could always add non-numbers later
<bkardell_> heycam: does css really support positive and negative values?
<dbaron> s/values/zeroes/
<Rossen___> q?
<bkardell_> TabAtkins: in calc, yes - we use the js semantics -- once you exit the calc no... it can affect the infinity
<dbaron> TabAtkins: yes, but only inside of calc()
<bkardell_> fantasai: I dont think you can parse one in?
<bkardell_> dbaron: you can write an negative 0, but it is just 0
<bkardell_> TabAtkins: if you produce a negative 0 as a result of the calc, you can have a negative 0
<bkardell_> Rossen___: is there a use case for that?
<bkardell_> TabAtkins: consistency with JavaScript?
<bkardell_> Rossen___: so we _want_ that in this case? :)
<bkardell_> TabAtkins: you can insert directly via typed om, actually
<bkardell_> TabAtkins: anyone have an objection to sign() restricted to numbers only?
<bkardell_> Rossen___: any objections?
<astearns> cbiesinger: Tab explained you get negative zero by dividing by negative infinity, which you get by -1/0
<bkardell_> RESOLVED: add the sign() function as described in the issue, restricted to numbers only

@tabatkins
Copy link
Member

Added sign() in 8e3fb63.

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

4 participants