- From: Tab Atkins Jr. via GitHub <sysbot+gh@w3.org>
- Date: Wed, 06 Nov 2024 00:26:24 +0000
- To: public-css-archive@w3.org
4 is necessary because the timing of substitution of `var()`s in fallback would change. Right now, with `var(--foo, var(--bar))`, you know exactly what the bounds of the fallback is, so you can avoid actually interpreting it unless it's needed. If `var(--bar)` doesn't exist or whatever, you won't even know unless fallback actually gets triggered and you have to process the fallback tokens. With this change, you won't always be able to do that, so you'll have to do the substitution eagerly, as part of processing the outer `var()`. You have to do substitution inside-out, so `var(--foo, var(--bar))` might turn into `var(--foo, guaranteed-invalid)`, and that needs to still be grammatically valid so that it can sub in `--foo`'s value if possible; the invalidity of the fallback shouldn't matter unless you actually use it. 5 is a consequence of that, just removing the [currently specified behavior](https://drafts.csswg.org/css-values-5/#invalid-substitution) that the presence of a guaranteed-invalid value immediately makes the property IACVT. > Are you saying that for [...] the computed value of --x on #child is now <guaranteed-invalid> rather than foo? Right, like @ExE-Boss says, that's luckily already the case; see <https://drafts.csswg.org/css-values-5/#invalid-substitution>. [Here's a testcase demonstrating it:](https://software.hixie.ch/utilities/js/live-dom-viewer/?%3C!DOCTYPE%20html%3E%0A%3Cstyle%3E%0A%23parent%20%7B%0A%20%20--x%3A%20green%3B%0A%7D%0A%23child%20%7B%0A%20%20--x%3A%20var(--unknown)%3B%0A%20%20background%3A%20var(--x)%3B%0A%7D%0Adiv%20%7B%20padding%3A%2020px%3B%20margin%3A%2020px%3B%20border%3A%20thin%20dotted%3B%20%7D%0A%3C%2Fstyle%3E%0A%3Cdiv%20id%3Dparent%3E%3Cdiv%20id%3Dchild%3E%3C%2Fdiv%3E%3C%2Fdiv%3E) ```html <!DOCTYPE html> <style> #parent { --x: green; } #child { --x: var(--unknown); background: var(--x); } div { padding: 20px; margin: 20px; border: thin dotted; } </style> <div id=parent><div id=child></div></div> ``` (The #child ends up without a background color, because --x is invalid on it. It doesn't inherit the `--x: green` value from its parent. I think, to be a little more specific, the rule would be that [the substitution algo for the function](https://drafts.csswg.org/css-values-5/#substitute-arbitrary-substitution-function) doesn't define a fallback value, substitution failure causes the failed substitution function to substitute as itself, but with its tokens marked as "meaningless", which causes them to have no behavior and not match any grammar except the "anything goes" ones like `<declaration-value>`, so trying to sub it into something else is guaranteed to fail (unless those tokens happen to fall into the fallback of a parent subsitution function). So, yeah, the computed value will be `var(--unknown)`, but it won't be reinterpreted on a child that happens to have a `--unknown` defined; it'll always be an (invalid for substitution) `var(--unknown)` set of tokens. This has a few effects, all of which are good imo: * It means we can abstract the full contents of a var() into a custom prop and substitute it in later, with no behavior change. That is, `--foo: green; color: var(--foo, var(--unknown));` works today; this change ensures that abstracting that to `--foo: green; --contents: --foo, var(--unknown); color: var(var(--contents));` also works exactly the same way. When we resolve `--contents`, the `var(--unknown)` fails, causing the computed value of `--contents` to remain exactly `--foo, var(--unknown)`, but with the `var(--unknown)` tokens marked as "meaningless". Then substitution into `color` produces `color: var(--foo, var(--unknown))`; since the "meaningless" tokens are in the fallback's `<declaration-value>`, that still grammar-checks successfully, and then substitution succeeds. Because the tokens are now "meaningless", they're not actually treated as a substitution function in `color`; importantly, if `--contents` is inherited into a child who *does* have `--unknown` defined, it won't suddenly start successfully substituting. * There's now no meaningful difference in behavior between `--foo: rgb(invalid stuff);` and `--foo: var(invalid stuff);`; authors no longer really see a behavior difference for invalid content based on the class of function. * Existing custom props containing non-CSS content that happens to *look* like a CSS function won't suddenly change behavior if we make one of those functions a substitution function, unless they're unlucky enough to actually match the function's grammar. So a random custom prop containing `--foo: if(1 < 2) { ... };` and one containing `--foo: my-if(1 < 2) { ... };` will continue to be treated the same after we start parsing `if()` as a substitution function (since that's invalid syntax for it). * Failed substitution can still be caught by `var()` with a fallback argument (or similarly, `inherit()` with a fallback), so existing code expecting such a failure to cause the custom property to become the guaranteed-invalid value (as the spec says today) and replacing it with a fallback will still work. -- GitHub Notification of comment by tabatkins Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/11144#issuecomment-2458463481 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Wednesday, 6 November 2024 00:26:25 UTC