Skip to content

[css-values-4] What happens to sign(%) when % has no meaning? #12204

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
andruud opened this issue May 16, 2025 · 14 comments
Open

[css-values-4] What happens to sign(%) when % has no meaning? #12204

andruud opened this issue May 16, 2025 · 14 comments
Labels
css-values-4 Current Work

Comments

@andruud
Copy link
Member

andruud commented May 16, 2025

Spin-off from #12192:

In e.g. width: calc(1px * sign(10% - 10px)), the result depends on what % resolves to, and that's fine. However, what about:

z-index: sign(10%);

Percentages aren't accepted by z-index, and so they don't really resolve against anything. #12192 (comment) suggest that sign() should take the value "as-is" (use the sign of the literal percentage value), but that doesn't work for e.g.:

z-index: sign(10% - 1);

By default I'd expect both examples to be invalid at parse-time.

@andruud andruud added the css-values-4 Current Work label May 16, 2025
@andruud andruud changed the title [css-values-4] What happens sign(%) when % has no meaning? [css-values-4] What happens to sign(%) when % has no meaning? May 16, 2025
@Loirooriol
Copy link
Contributor

Loirooriol commented May 16, 2025

https://drafts.csswg.org/css-values/#calc-type-checking

If, in the context in which the math function containing this calculation is placed, <percentage>s are resolved relative to another type of value (such as in width, where <percentage> is resolved against a <length>), and that other type is not <number>, the type is determined as the other type, but with a percent hint set to that other type.

Otherwise, the type is «[ "percent" → 1 ]», with a percent hint of "percent".

It seems to me that the "otherwise" covers the case of percentages not resolving against anything because they aren't valid.

So z-index: sign(10% - 1) is invalid (like z-index: calc(10% - 1)) because you are trying to add a value with type «[ "percent" → 1 ]» and a value with type «[ ]».

@andruud
Copy link
Member Author

andruud commented May 19, 2025

@Loirooriol OK, thanks. I guess that would explain how sign(10%) can be valid while sign(10% - 1) isn't.

@cdoublev
Copy link
Collaborator

My understanding is that z-index: sign(10%) is also invalid since the type of 10%, which is [percent → 1] with a percent percent hint, cannot be made consistent with the input calculation type, which is [] for <integer>.

@andruud
Copy link
Member Author

andruud commented May 19, 2025

@cdoublev Isn't [percent -> 1] the input type, and <number> the base type, in which case it can be made consistent?

The return type [of sign()] is a <number>, made consistent with the input calculation’s type.

@cdoublev
Copy link
Collaborator

Yes, I have got things completely mixed up. (This is not the first time, sorry.)

After a closer look at it, my (new) understanding is that the type made consistent is [] with a percent percent hint, which does not match <integer>/<number>.

If the context does not allow <percentage> values, then for the type to be considered matching the percent hint must be null.

@dbaron
Copy link
Member

dbaron commented May 19, 2025

Is it desirable for sign() to accept an argument with a [ <percent> -> 1 ] type without requiring that percentages resolve to something? It seems like a confusing distinction to me.

(Fixing it seems a little tricky since I think it requires a new percent hint concept that we don't already have: the concept that percentages resolve to something but we don't have a requirement for what.)

@andruud
Copy link
Member Author

andruud commented May 21, 2025

It seems that Firefox and Chrome agree that both z-index:sign(10%) and z-index:sign(1% - 1) are invalid, whereas Safari only thinks that z-index:sign(1% - 1) is invalid. (https://jsbin.com/wodiwagoye)

Is it desirable

It doesn't seem too unreasonable that z-index:sign(10%) should work. I would be satisfied with @Loirooriol's explanation had it not been for the inconsistency @cdoublev found. But I don't have strong opinions on this as long as it's defined.

@tabatkins
Copy link
Member

tabatkins commented May 21, 2025

Edit: nm, I'm misreading my own spec. One second....

@tabatkins
Copy link
Member

1% - 1 fails due to a type mismatch (adding the types returns failure); it's an invalid calculation no matter what it's used in. (Percents never resolve against pure numbers in a calc sense, to avoid ambiguous types.)

Per spec, z-index: sign(10%) is invalid as well. Since the % doesn't resolve against anything, its type is [percent=>1] with a percent hint of "percent", per "resolve a type". sign() then returns a number, made consistent with its input; this gives it a type of [] with a percent hint of "percent". This then fails to match <number>, per the "match" operation, because %s aren't allowed in this context and so it only matches <number> if its percent hint is null.

So Chrome and Firefox are currently correct, Safari is wrong.

@weinig
Copy link
Contributor

weinig commented May 22, 2025

Is the "a percent hint of "percent", in resolving a type new? When I implemented this last summer, I was pretty sure that resolving a percentage like this did not set a hint at all.

@weinig
Copy link
Contributor

weinig commented May 22, 2025

I found it, 0edbe98, changed in October! So when implemented, Safari was right, but the spec has changed.

@tabatkins, what was the purpose of this change?

@tabatkins
Copy link
Member

Sorry, I failed to tag that edit against an issue. Searching in my email, looks like it was to address this comment #10840 (comment).

It causes the calculation to capture the fact that the calculation context doesn't do anything with a percentage, so I don't try and resolve it against something else and only happen to fail it later, like opacity: calc((10% + 50px)/100px). That sort of calc now fails when it tries to add 10% and 50px, as the percent hint on 10% isn't compatible with a length.

@dbaron
Copy link
Member

dbaron commented May 23, 2025

I don't understand how that edit doesn't break the entire percent hint concept and cause every calculation like 50px + 10% to fail (when in fact we want many of them to succeed when percentages are lengths).

(I also still think it's desirable for z-index: sign(10%) to fail. I guess I should say that a little more explicitly than just asking whether it should.)

@tabatkins
Copy link
Member

I don't understand how that edit doesn't break the entire percent hint concept and cause every calculation like 50px + 10% to fail (when in fact we want many of them to succeed when percentages are lengths).

I'm confused. The immediately preceding paragraph to that in the spec states that if percentages are resolved against another type, they get a percent hint of that other type. It's only percentages that stand on their own that get the "percent" percent hint.

(I also still think it's desirable for z-index: sign(10%) to fail. I guess I should say that a little more explicitly than just asking whether it should.)

Luckily that's exactly what happens, as I explain in #12204 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-values-4 Current Work
Projects
None yet
Development

No branches or pull requests

6 participants