-
Notifications
You must be signed in to change notification settings - Fork 675
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-variables] Substitution of invalid variables into other variables #5370
Comments
I personally don't agree with that, I think what we currently have now is the most consistent behavior. (Yes, there are arguments in both directions). Since FF, Safari, Chrome and the spec now all agree, this ship has sailed in my opinion. Even if the spec did change, I'd be reluctant to change the behavior in Chrome (again); we shouldn't flip-flop between behaviors constantly. If you want to avoid inheriting the (outer) value into some component, then explicitly set the custom property to |
The behavior is now inconsistent with standard properties actually.
color inherits by default and does not inherit above the component when This is what computed-time-value of |
So this is about https://bugzilla.mozilla.org/show_bug.cgi?id=1623396, right? Which landed in Firefox 76, which is most definitely not the most recent stable release (that was released mid-may, so we've been shipping this for more than two months). As I said in #4075 I'm not particularly a fan of the current behavior (I slightly prefer the previous one). That being said, I see arguments both ways, and switching behaviors back and forth is really unfortunate, as @andruud said. If the spec changes I'd be ok changing behavior in Gecko again, though given the discussion in #4075 and the fact that all browsers now agree on the behavior I think the value of the spec change needs to be huge.
Can you clarify? Your example with cc @tabatkins |
@emilio Acknowledged on all points, thank you for the corrections. Here is minimal var component example: The inner most --smaller-input, and any other instances nested within, will always use --bigger-input behavior now because no fallback behavior is possible with initial at computed-value-time now. (unless it's on the root or has no parents with the same var name) The library I'm working on is of course much more complex than that and has many many layers of "internal" variables that may compute to initial in any number of ways so I could use fallback behavior, all based on a small number of end-user input options. @andruud Please know I respect your opinion here even though I disagree with the conclusion. It wouldn't be a reasonable request for me to ask this if we can't coordinate with all 3 browsers to move forward. Perhaps an alternative path to allow the previous computed-value-time initial behavior could be added independently? I haven't given much thought to that but would you be more comfortable going in that direction? I think everyone will agree with both of you that it's really nice to have all 3 browsers on the same page (and agreeing with the current spec). |
"Internal" variables, huh? 🙂 You can use |
(Thinking about it some more:)
Yeah, that could be the way to go. It does seem useful to be able to control the IACVT behavior in your example (thanks for that BTW 👍). Not sure how though. Maybe it's an aspect of the property itself (in which case it's Some of this reminds me of #5055, though that's not quite going to work here as-is. (Linking anyway for inspiration). On the other hand, it seems easy to solve this problem in practice by just having the outer element of the component reset all the custom properties that shouldn't cross the boundary, and then an inner element can (attempt) to set the actual values for those properties. |
No worries! I'm glad the example was helpful Catching an exception sounds like the right track and I love the idea of an inline customizable fallback...
Yep, this is how I've worked around it in my library. It may be easy for small libraries but the real-world cost of my project is:
That solution with the inline fallback in a |
Copied over from #4075: It sounds like what you're wanting is for the guaranteed-invalid value to be preserved as it's substituted thru custom properties, so that the iacvt behavior of making the value unset only triggers on "real" properties (or perhaps on registered custom properties as well), and you can trigger fallback at any point in a variable chain (rather than only at the exact point where the guaranteed-invalid value is introduced). Is this right? This isn't an unreasonable request! In w3c/css-houdini-drafts#994 (comment) Amelia asks for the ability to explicitly allow a registered property to still assume the guaranteed-invalid value, which is currently only possible when you have a completely unrestricted grammar. Implicitly, this is recognizing that the guaranteed-invalid value actually is "valid" in some circumstances; it's guaranteed to never match the grammar of any predefined CSS property, but it's part of the value space (and thus, matches the grammar) of unregistered custom properties, or registered ones with unrestricted grammar. This is a different choice than what we've currently made in the spec, but it's not a wrong one. And I think I've talked myself into preferring it. It would be a minor behavior change, tho. @andruud, any thoughts? |
Hello @tabatkins,
Yes, you nailed it, succinct too. 😄 That definition of the behavior enables modular/independent/nestable css variable components Thank you! |
When you put it like that, it makes sense to me too. It would mean that any property that is IACVT becomes:
If we are recognizing guaranteed-invalid as "valid" in some cases, we must IMO also recognize that it's not permissible in all other cases. This has some consequences for cyclic at computed value time. We currently assign guaranteed-invalid to all custom properties in a cycle, regardless of their grammar. With this new way of thinking about guaranteed-invalid, we could only assign this value to custom properties which support it. In other words, non-universal registered custom properties in a cycle would become What bugged me initially in #4075 was the inconsistency that standard properties behaved in one way and custom propeties in another for no apparent reason. But the new model would "explain" the difference via what is allowed by the grammars, which seems satisfactory to me. (So even a standard property could in theory become guaranteed-invalid if it explicitly allowed it for some reason). I'm not sure how easy it is to make this change given that all browsers currently agree on the behavior. I'm also not thrilled about doing a 180. But since it seems to be what everyone wants, and I'm warming up to the idea myself, I suppose we could try. 🤷♂️ |
While it's a near-reversal in behavior, we're not just swapping our opinion back, we're actually going for a new argument that happens to look similar to the older behavior. I'm okay with that. ^_^ I'll get some edits in soon. |
Since we are leaving a state of "perfect interop", we should make sure Apple agrees with the change before making the edit. I don't think this is valuable unless all browsers are willing to change their behavior. @tabatkins who on the Webkit team would be a good person to comment on this? |
I think we'd be willing to follow if other browsers think there isn't a compat concern. |
@smfr Thanks, I can investigate the compat situation by adding a use-counter in Chrome. |
I'm not sure how specific Plus, others were at least experimenting with the previous chrome/firefox behavior too: https://twitter.com/gavinmcfarland/status/1289010777651847168 so use-counter would almost have to determine intention if it's just out there and now broken somewhere. Tangentially, If the change moves forward, the current-spec-behavior can be reproduced when #5325 is resolved by using If the change doesn't move forward, there is no easy path alternative to reach the IACVT fallback in the nested/modular situation unless your new |
Since the issue was re-opened in Chromium bug tracker specifically to implement the use-counter, my point may not have been clear... @andruud @emilio @smfr (please correct me if I am wrong) Problem: A use-counter cannot measure compatibility with the developer's intention unless you also measured before the change a few months ago and subtract those. Reason: Any CSS causing IACVT that now specifically inherits a non-initial value from an ancestor (based the spec's definition) was exclusively either:
All other behavioral branches in the IACVT cases are identical in an end-result behavior between the two implementations and are therefore also not a measurement for compatibility with the author's intention. The most likely branch, # 3, is the reason it hit my radar, and also this person's: https://twitter.com/gavinmcfarland/status/1289010777651847168 |
There is a desire to change how this works (again) [1], but since all browsers agree on the current behavior, we have to be careful with changes. Hence this CL adds a detailed use-counter. The behavior we want to change can be illustrated with the current example: <style> #outer { --x: foo; } #inner { --x: var(--unknown); } </style> <div id=outer> <div id=inner></div> <div> Current behavior: the computed value of --x on #inner behaves as 'unset', and hence becomes ' foo'. Desired behavior: the computed value of --x on #inner becomes the guaranteed-invalid value [2]. More generally, any property whose grammar "supports" the guaranteed- invalid value shall become guaranteed-invalid if it's invalid at computed-value time (IACVT) [3]. Properties which currently supports this are: unregistered custom properties, and registered custom properties with universal syntax. This CL avoids counting cases where the new behavior wouldn't make a difference: - If the property doesn't support <guaranteed-invalid> - If the property is non-inherited without an initial value - If the property would anyway inherit <guaranteed-invalid> [1] w3c/csswg-drafts#5370 [2] https://drafts.csswg.org/css-variables/#guaranteed-invalid-value [3] https://drafts.csswg.org/css-variables/#invalid-at-computed-value-time Bug: 1110188 Change-Id: I1a230e03b59ee3490166e92e1e83586a681301a0 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2352871 Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/master@{#797612}
I've added the use-counter in Chrome, I'll report back in October when I have some data. |
Hey guys, sorry to bump but it's been a while past October now, is there an update on this? |
I think the counter is |
Hello @tabatkins @emilio @andruud May we continue this discussion please? Thank you, edit: Thank you! https://groups.google.com/a/chromium.org/g/blink-dev/c/0xrbzYe_vxU/m/52xVJHTICQAJ |
I now have approval to ship this change in Chrome, for what that's worth. This is contingent on the spec change happening first, and other vendors still being on board with the change. (@emilio @smfr)
The Chrome use-counter is at ~0.02% of page loads, and I couldn't find any breakage among that sites that showed up related to the use-counter. (See I2S post for details). So it doesn't appear to be a huge compat concern. (For Chrome that is). |
- Export "registered custom property". - Export "universal syntax definition". - Fix a "the the". - When parsing against the syntax, we probably want invalid at computed-value time, and not guaranteed-invalid? Somewhat related to: w3c/csswg-drafts#5370
…1020) - Export "registered custom property". - Export "universal syntax definition". - Fix a "the the". - When parsing against the syntax, we probably want invalid at computed-value time, and not guaranteed-invalid? Somewhat related to: w3c/csswg-drafts#5370
There is a desire to change how this works (again) [1], but since all browsers agree on the current behavior, we have to be careful with changes. Hence this CL adds a detailed use-counter. The behavior we want to change can be illustrated with the current example: <style> #outer { --x: foo; } #inner { --x: var(--unknown); } </style> <div id=outer> <div id=inner></div> <div> Current behavior: the computed value of --x on #inner behaves as 'unset', and hence becomes ' foo'. Desired behavior: the computed value of --x on #inner becomes the guaranteed-invalid value [2]. More generally, any property whose grammar "supports" the guaranteed- invalid value shall become guaranteed-invalid if it's invalid at computed-value time (IACVT) [3]. Properties which currently supports this are: unregistered custom properties, and registered custom properties with universal syntax. This CL avoids counting cases where the new behavior wouldn't make a difference: - If the property doesn't support <guaranteed-invalid> - If the property is non-inherited without an initial value - If the property would anyway inherit <guaranteed-invalid> [1] w3c/csswg-drafts#5370 [2] https://drafts.csswg.org/css-variables/#guaranteed-invalid-value [3] https://drafts.csswg.org/css-variables/#invalid-at-computed-value-time Bug: 1110188 Change-Id: I1a230e03b59ee3490166e92e1e83586a681301a0 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2352871 Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Original-Commit-Position: refs/heads/master@{#797612} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 4157bfe188b1da73ef93f5d1f4dc0121f0208ff9
https://bugs.webkit.org/show_bug.cgi?id=241433 is the WebKit bug for this. |
I know this issue was closed, but it seems like this comment from @tabatkins was never addressed:
It's possible I'm missing something, but it seems there is still no way to make the initial value of a registered custom property with a syntax other than |
In the spec it says to treat css variables as "unset" instead of "initial" if any compute results in the value becoming 'initial'.
(if the variable is directly set to
initial
without a compute, it behaves asinitial
)https://drafts.csswg.org/css-variables/#invalid-variables
Until the most recent stable release of FF and Chrome, both browsers were ignoring this. #4075
I would like to have this wording changed to match the previous behavior of FF and Chrome:
for the following reasons:
Standard properties with inheritance treat
initial
as sort ofunset
, except the behavior is "unset since the root". For example, see this demonstration on the inheritedcolor
property: https://developer.mozilla.org/en-US/docs/Web/CSS/initialthe spec specifically says that the cascade value should be thrown out by the time it's become invalid at computed-value time:
initial
is the guaranteed invalid behaviorcomputing to
initial
to override a variable (and use fallbacks when referenced) should still be an option but is no longer possible. Now the guaranteed-invalid value is only guaranteed to behave theinitial
invalid value at the:root
and is more of an edge-case than a guarantee we could rely on.var(.., UNREACHABLE)
. (This is arguably the single most important reason the previous FF and Chrome behavior was very useful)^ number 5 there should be a deal breaker for anyone wanting to make css-variables part of their library, even though the decision was recently made to follow spec, the decision had arguments on both sides, ultimately landing in a spot that removes a lot of possibility and readability from CSS variables.
Understanding the reasons listed here, especially num 5, I believe both @andruud and @emilio would agree that the behavior as it was before should be established as correct in the Spec and the browser changes be reverted. (& Safari should come along too)
Thank you for your consideration
The text was updated successfully, but these errors were encountered: