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-4] How to serialize infinite values? #3768

Closed
tabatkins opened this issue Mar 26, 2019 · 8 comments
Closed

[css-values-4] How to serialize infinite values? #3768

tabatkins opened this issue Mar 26, 2019 · 8 comments

Comments

@tabatkins
Copy link
Member

In an expression like calc(1/0 * 1px), it resolves to ∞px. Per the simplification rules currently defined, this should serialize without the calc() wrapper. What should a value like that serialize as, tho?

I'm considering specifying that infinite values serialize as a 1/0 expression, even tho divisions are technically resolved away before serialization happens.

@AmeliaBR
Copy link
Contributor

Note that whatever you choose would also be used for NaN, per this line:

If a top-level calculation (a math function not nested inside of another math function) would produce a NaN, it instead produces +∞.

Your suggestion seems the simplest from a syntax perspective, if we just need something for serialization. It's a little bit confusing that you simplify down other functions only to replace them with a different function, but the important part is that the end result is clearly defined.

Would your simple version then be calc(1px/0), with 1px replaced by whatever is the canonical unit for the correct dimension?

@tabatkins
Copy link
Member Author

Would your simple version then be calc(1px/0), with 1px replaced by whatever is the canonical unit for the correct dimension?

Yes.

@tabatkins
Copy link
Member Author

So this is actually a larger issue; in level 3 I could always simplify a valid calculation into a summation of ordinary units, and the current serialization text assumes that is still true. Adding in the min/max/clamp functions invalidated that (requires a summation of units and an arbitrary number of functions), but adding in unit algebra blew it away completely. There are now valid calculations that I can't simplify down further than an operator-tree.

So, to what degree to I want to simplify? I could still require simplifying mult/div by numbers, and require that summations be sorted in the existing specified way, to maintain compat with Level 3 calc() simplifications. I don't think I want to go any further than that; even if I could simplify in some cases (like simplifying 1in / 10px * 1em to just 9.6em) it would be complex to specify and not really clear to authors what's happening, I think.

So my proposal is precisely that:

  • mult/div by a literal number must be simplified away
  • summations must be sorted in a compatible way to the old specification
    • ordinary units are sorted alphabetically by unit (with number and % in their specified positions), followed by functions and more complex sub-calculations (wrapped in parens) in source order.
  • infinite values are serialized as 1/0, with the numerator having the appropriate canonical unit for the type

Still not completely sure what to do with NaNs. They're fully infectious; a NaN argument to any function results in NaN, and a NaN at any depth in a calculation causes the top-level calculation to be NaN. Maybe simplify the whole thing to calc(1/0)? Do this even if the original math function wasn't calc(), like clamp(0px/0, 1px, 50px) serializing to calc(1/0)? That has a possibility of being valid, tho; z-index would accept that value. I think I need to define an always-invalid math function form, like a literal calc(), which is grammatically valid in itself, but has no type and thus is invalid in all contexts it can ever be placed.

@tabatkins
Copy link
Member Author

Hm, further details on NaN:

  • Actually, I do know what type a NaN is; I can do type calculations at parse time, before I know what the values are. (And that's necessary to be able to do grammar validation of calc() at all.) So I could serialize NaN as an appropriate infinite calc(), if I want.
  • on the other hand, maybe I just want to go the other way and invoke "invalid at computed-value time" for NaNs. This would mean no simplification (or confusing function-switching) necessary, but I'm not sure how difficult invoking that machinery is. Need implementor opinions on this.

@Loirooriol
Copy link
Contributor

IMO it would be unexpected to serialize NaN as calc(1/0). calc(0/0), with the numerator having the appropriate canonical unit for the type, would make more sense.

@tabatkins
Copy link
Member Author

Ah yeah, makes sense.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed How to serialize infinite values?, and agreed to the following:

  • RESOLVED: Use calc(1/0) and calc(0/0)
The full IRC log of that discussion <dael> Topic: How to serialize infinite values?
<dael> plinss: Tab sent regrets, anyone want to talk about this?
<dael> github: https://github.com//issues/3768
<dael> AmeliaBR: I can go over quickly
<dael> AmeliaBR: Issue is that at serialization stage before computed style we say divisions are simplified. Sometimes means you have /0 situation or other situations with infinite or NaN values. WE havethat NaN is +infinity but how to serialize.
<dael> AmeliaBR: Prop is serialize it as a calc expression as something/0 where something is appropriate to dimension you're using 1px, 1deg, 1ms
<dael> AmeliaBR: This would only be exposed in serialized values
<dael> AmeliaBR: Catching up on issue discussion between oriol and TabAtkins where NaN should have own unique serialization diff than infinity
<dael> AmeliaBR: We want something predicable and consistent but not too complicated b/c used in a lot of places. Jsut for intermediate serilization
<dael> fantasai: Seems infinity is calc(1)/0 and NaN is calc(0)/0
<dael> plinss: negative infinitiy is calc(-1)/0?
<fantasai> calc(1/0) and calc(0/0)
<dael> fantasai: Yep
<dael> AmeliaBR: And all of these would hold on to a unit so it's calc(1px)/0
<dael> fantasai: Makes sense
<dael> gregwhitworth: Consider none as a keyword?
<fantasai> s/none/NaN/
<dael> fantasai: Then we'd need to make it for all CSS and why would you want that
<dael> gregwhitworth: For this reason? B/c we're spec in a weird way
<dael> fantasai: THis is better than a global keyword that's a number that doesn't exist. I don't think it helps anyone
<dael> emilio: Prob doesn't work with dimensions
<dael> fantasai: That's an important point
<dael> plinss: Other alt is keywords for NaN and infinityfor only in calc. Curious if they have an actual use somewhere else
<dael> AmeliaBR: We do havesome prop that have an infinity keyword and that is treated diff than a calc expression that computes to inifity. It's the infinite keyword in animations. Not sure where else
<dael> fantasai: We should go with calc-based serialization. It comes up in serializing calcs and that way we don't need keywords for units. it's built into the method
<dael> plinss: Objections?
<dael> RESOLVED: Use calc(1/0) and calc(0/0)
<dael> emilio: How does NaN behave? Like NaNpx body?
<dael> AmeliaBR: I assume keep current rule where treated as +inifinity and then clamps per property rules
<dael> emilio: Wouldn't be better to keep as computed time for clamping and not care about serialization?
<emilio> heh
<dael> AmeliaBR: Serialization simplifies multiplication and division so it has to be simplified. Going down to a standard division structur
<dael> AmeliaBR: If you spec calc(3/3) at serialization you get 1. If you spec calc(3/0) we're saying at serialization you get 1/0
<dael> plinss: GIven our existing rules we have to do this
<dael> emilio: calc(1/0) doesn't parse anywhere, right?
<dael> AmeliaBR: I don't know. If we have people rejecting at parse or doing own thing at serialization
<dael> emilio: Pretty sure gecko rejects at parse time. When we impl min/max may have to change
<fantasai> http://software.hixie.ch/utilities/js/live-dom-viewer/?%3C!DOCTYPE%20html%3E%0A%3Chtml%20style%3D%22background%3A%20red%3B%20background%3A%20calc(1px%2F0)%20calc(1px%2F0)%20green%3B%22%3E
<dael> fantasai: Doesn't appear to be the case ^
<dael> fantasai: If we enter as keyword still won't parse.
<fantasai> s/Doesn't/Does/
<dael> fantasai: Gecko does not parse
<dael> AmeliaBR: Same for Chromium
<dael> AmeliaBR: But we're extending number of pss divisions poss. Allowing to devide values withunits and some units might be 0 so need robust math rules
<dael> emilio: But then how to serialize this is only small part, need to spec how behave. You're introducing them into layout
<dael> AmeliaBR: There is an extended new section on range checking
<dael> AmeliaBR: that says any infite values are clamped to min/max allowed. emilio is right most prop don't have explicit min/max value allowed
<AmeliaBR> https://drafts.csswg.org/css-values/#calc-range
<dael> AmeliaBR: That prop still part of spec needs to be discussed. I don't know if need to hold off discussion of serialization
<dael> emilio: Generally the spec saysclamp and apply transformations as early as possible. calc(10px) serialize to 10px. Serialization might not be an issue depending on how spec to behave
<AmeliaBR> s/That prop still part of spec/That part of spec probably still/
<dael> myles: Not sure should spec max for every prop. Browsers may vary. Some browsers might be able to handle a really big width and some can't
<dael> emilio: Agree
<dael> myles: Tons of impl specific limits like nesting depth that aren't written. These max should be with those
<dael> AmeliaBR: Good point. Should lead to not clamp too early. Eventual clamp will be impl specific so should only happen when it has to. If we just propagate mathematical infinity it helps interop and serialization stage
<dael> emilio: Reasonable answer
<dael> plinss: Anything else?

@tabatkins
Copy link
Member Author

All right, specced. This happens at the top-level math function; I'm not trying to be smart and do the magic serialization at the deepest point or anything.

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

5 participants