-
Notifications
You must be signed in to change notification settings - Fork 639
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] Clarifying serialization of negative zero and expression simplification #9750
Comments
My understanding is that ideally it should be serialized as I think safari incorrectly simplifies percentages (percentage basis can be negative in some properties) and that's a bug on their end, though arguably you could simplify the "equal" percentages. That is probably a separate issue tho. |
Possibly related: document.body.style.marginRight = "calc(-0% + -0em + -0ic + -0lh + -0px + -0vw)";
document.body.style.marginRight;
|
I thought that negative zero is always tokenized and parsed as positive zero and that negative zero can only be produced by calculations. So serializing to I've actually been using
The context is a bit different for me as the purpose is to calculate what is possible in dev tooling without altering how a browser would parse these. |
The CSS Working Group just discussed
The full IRC log of that discussion<Frances> RESOLVED: Allow the modulus parameter to be optional in the case of rounding numbers and default to 1.<Frances> Tab: Track positive 0 and negative 0 separately, could result in different infinities in separate cases. We mostly separate this away. Could become an unsigned 0. <Frances> Tab: One case where it isn't true if the 0 is a percentage so could be positive or negative in +0% and -0%. How important is this? We could just stick with the spec to imply need to verify if clear, and care about percentages and simplify. <TabAtkins> max(0%, -0%) (or min(), or clamp()) <Frances> Alan: Can we see if the spec is clear, does the spec talk enough about positive and negative percentages? <Frances> Tab: Would have to keep the max function with both arguments, carefully threading a few arguments. <Frances> David: If the goal is serialization round tripping, we don't parse negative 0 into a negative 0. <TabAtkins> min(1% / -infinity, 0%) <Frances> Tab: If writing a solution similar to it, would still have to parse in the current semantics. <Frances> Tab: Currently it should require both arguments to be preserved. <emilio> theq+ <emilio> err <emilio> q+ <astearns> ack emilio <Frances> Emilio: Preserving the original syntax, we need to serialize it to something else. Infinity basically normalized the serialization, we don't preserve the actual author documentation. <Frances> Tab: Not a problem to simplify more aggressively in the use case in it does not matter. <Frances> Alan: Write tests for the spec based on the test production. <Frances> Emilio: Could become a complicated code path, serializing -0%, and draw a calc tree. <TabAtkins> happy to figure out how to normalize such an expression, at minimum <Frances> Alan: Any other concerns? <Frances> David: Like the idea of trying to keep it simple for a use case. <dbaron> s/David:/dbaron: Not really an implementor as far as this code is concerned, but I/ <dbaron> s/a use case/something without much of a use case/ <Frances> Tab: We can resolve to at minimum serialize in case of a complex tree. <Frances> PROPOSAL: -0% serializes to a normalized form <Frances> RESOLVED: -0% serializes to a normalized form |
Tab seemed to agree during the call, but it doesn't seem to be the case from https://drafts.csswg.org/css-syntax-3/#consume-numeric-token For Browsers don't currently accept percentages in denominators, but they agree with plain numbers: document.body.style.zIndex = "calc(1 / -0)";
getComputedStyle(document.body).zIndex; // A very negative number, unlike for `calc(1 / 0)` you don't need |
Right now, we only have the "normalized serialization" for inf/nan values when they emerge at the top-level. That is, if the entire expression simplifies to inf/nan, we serialize it in a specific way (rather than requiring more of the exact tree to be preserved). This doesn't quite work the same here - if an entire expression simplifies to -0%, we'll just serialize it as
Dang it, I keep forgetting that that does work. In that case, then, I think the issue is indeed no-change. If an expression simplifies to -0%, and this blocks further simplification, then you can simply serialize it as such. So, yes, I think I (a) will add a note to the spec explicitlly calling out that -0/etc does work in a calculation, so I stop forgetting, and (b) add a test for this case. |
The I was really sure that negative zero can not be produced by parsing, but now not so much anymore :) |
BTW, https://rawgit.com/tabatkins/parse-css/master/example.html says And not for percentages, but |
There was a recent issue were this was discussed and it was mentioned there that negative zero is written very specifically in css-values-4 as Edit: if there is test coverage than this is cleared up, thanks 🙇 |
These tests are relatively recent. I am pretty sure
Based on #7472, CSS were inadvertently producing tokens representing a negative zero. Now I am not sure whether interpreting |
I have bisected Firefox. IMO if we have the concept of negative zero, Also #4110 was closed "in favor of the metabug for better JS alignment", and in JS, |
Recently I was discussing with @emilio how signed zeroes should be serialized in calc expressions, and couldn't find a clear answer in the spec.
For example, an expression like
max(1% / -infinity, 0%)
which should simplify tomax(-0%, 0%)
. Without knowing if the percentage basis is positive or negative, it can't be simplified further since zeroes of different signs are not considered equivalent in min/max functions.It looks like currently Chrome and Firefox serialize this as
max(0%, 0%)
while Safari doescalc(0%)
. I'm not sure which one of these is correct.max(-0%, 0%)
is perhaps another possibility.I found two parts of the spec that look to be relevant.
The serialization steps mention infinities and NaN but don't have any explicit instructions for negative zero. The numeric value should be clamped to the allowed range, but the allowed range may include negative values.
10.9.1. Infinities, NaN, and Signed Zero mentions that if a top level calculation simplifies to a negative zero, it should be "censored into a standard representable value".
Could that apply here? The example expression doesn't fully simplify, but the only two possible resulting values would be equivalent to 0%, so
calc(0%)
seems reasonable in this case.But I'm not sure if that would work if there are additional arguments. Would it also be ok to simplify something like
max(-0%, 0%, 1%)
tomax(0%, 1%)
if it's the top-level expression? Does it make sense in general to eliminate duplicated values? Safari serializesmax(1%, 1%, 1%)
ascalc(1%)
, while Chrome and Firefox keepmax(1%, 1%, 1%)
.The text was updated successfully, but these errors were encountered: