-
Notifications
You must be signed in to change notification settings - Fork 688
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] Allow an inline way to do "first value that's supported" #5055
Comments
In :root {
--fg: first-supported(lch(30% 130 300); blue);
} |
It could be good to accept a CSS-wide keywords, e.g.
if neither |
CSS-wide keywords need to be the cascaded value, which they won't be in this case. So putting CSS-wide keywords in such a function doesn't work with the current model. Not saying it's impossible, and we're already effectively reverting at computed-value time (#4155), so perhaps we should go all-in and generalize to all CSS-wide keywords and spec it properly. :P EDIT (one year later): Since my original comment we have allowed CSS-wide keywords in |
Strong +1 I have proposed |
Are there others? |
toggle(), and now mix() |
|
Parse failure. (In your example, it's fine in the custom property, because the custom property doesn't see a
Parse time. This is a pure functionality substitution for just writing the property twice and using the last one that parses. (As stated above, it's not resolved in a custom property, as only var() functions are. But once substituted, the late parse-time validation that can trigger IACVT takes over.)
Parse failure.
Yes, since it's a parse failure. ^_^
Then it successfully parses (so long as the |
The CSS Working Group just discussed
The full IRC log of that discussion<emeyer> Topic: [css-values-4] Allow an inline way to do "first value that's supported"<emeyer> github: https://github.com//issues/5055 <emeyer> TabAtkins: This is trying to address an issue that’s become more prevelant as variables have become more common. <argyle> right at the good part! <emeyer> …CSS lets you use new features and fall back to old ones by writing something twice. <emeyer> …Variables break this. We assume things are valid at parse time, and only find out later whether or not they are. <emeyer> …This same problem is going to come up with more things that do things at parse time. <lea> q? <lea> q+ <emeyer> …Proposal is to allow things to sub in the first thing the UA understands at parse time. <dbaron> ... has to be the full value of the property <emeyer> …This will need some clarification about how it can or can’t be nested. So we’ll want to define some contextual stuff. <emeyer> …Overall it’s an attempt to get parse-time fallback behavior. <fremy> huge +1 of course <astearns> ack lea <emeyer> lea: This would be incredibly useful. Would it be availabnle in descriptors as well? <emeyer> TabAtkins: I don’t see why not. <emeyer> s/availabnle/available/ <emeyer> florian: So this is no different than writing a thing twice? <emeyer> TabAtkins: Correct. <emeyer> emilio: This would go away at parse time? <florian> s/So this is no different than writing a thing twice?/So this is no different than writing a thing twice if you use it without variables? <emeyer> TabAtkins: Correct. <emeyer> emilio: That seems fine. <emeyer> astearns: Any concerns? <emeyer> …So the resolution is to add `first-of` to Values. Any objections? <emeyer> florian: Just wondering about the name of it. If people see this out of context, will they think it’s a list manipulation thing? <lea> Yeah, as much as I like terse names, first-of() is confusing <lea> q? <lea> q+ <emeyer> TabAtkins: It’s possible there will be misinterpretation, but at least they’ll run into confusion quickly. <lea> q- <miriam> +1 first-valid <smfr> +1 on first-valid <emeyer> florian: How abotu `first-valid`? <emeyer> s/abotu/about/ <emeyer> TabAtkins: I like it. <fremy> @emeyer: that was me <emeyer> fremy: I support that. <emeyer> astearns: We can bikeshed the name later. Any objections to the idea? <emeyer> …We are resolved to add `first-valid` and please add an issue to bikeshed the name once we better understnad the scope. <astearns> RESOLVED: add `first-valid` and please add an issue to bikeshed the name once we better understnad the scope <emeyer> RESOLVED: add `first-valid` and please add an issue to bikeshed the name once we better understand the scope |
I opened a nearly identical issue to this earlier today that thankfully, @Loirooriol caught before I went too far down that rabbit hole. Originally, I started with the function name, Re the functionality, the functionality is nearly identical but likely not 100% the same. Specifically in regarding to element {
color: prefer(var(--property-1), var(--property-2), var(--property-3), color(display-p3 1 0 0.87), black);
} This is something I advised against in my original spec proposal, but @Loirooriol very correctly pointed out that simply using identifiers (e.g. I think this proposed spec and the one I posted share the same syntax, essentially this: prefer(value1 [, value2?, value3?, ..., valueN?]) |
From the comments above,
If it is validated at parse time (in standard properties), how should serialize Is it ok that edit: maybe I misunderstood "the custom property doesn't see a
CSS Values defines the set of valid values for properties and in many other places but it seems sane to consider something invalid when it is not explicitly valid. Besides, most substitution functions in CSS Values 5 cannot be valid in descriptor values. For example, |
I actually ran into a use case today where this would not just be syntactic sugar, but a substantive improvement. In a web component, I have a user-provided I can do the latter using I’ve also been thinking, instead of the weird "function that can only be used for a property’s whole value" restriction, perhaps it would make more sense to be able to use CSS's regular fallback mechanism by being able to "mark" certain declarations as "don't drop these, I might need them as fallbacks"? More heavyweight to implement, but potentially better DX. There have also been some thoughts about an @-rule that does this in the Or, if we keep it as a function, perhaps we can relax the restriction to "only one of these per declaration"? So that one could do things like: background: linear-gradient(to right first-supported(in var(--color-space), in oklab, ), var(--color-stops)); Instead of this that the current proposal requires: background: first-supported(
linear-gradient(to right in var(--color-space), var(--color-stops)),
linear-gradient(to right in oklab), var(--color-stops)),
linear-gradient(to right, var(--color-stops))
); |
I really needed it many times trying to get something like |
This is not as useful for static things like that, as you can just do: :root {
--viewport-height: 100vh;
@supports(height: 100lvh) {
--viewport-height: 100lvh;
}
} Then use |
Right, but it gets messy. |
We had literally this exact case today, with the gradient interpolation that we wanted to resolve into a “space” when it is not supported. Having an ability to use the I guess the main issue with this will be that it should be invalid as a value for non-registered custom properties, so there won't be a way for the authors to specify two instances of it in the runtime? Or we will be ok with making the declaration invalid at computed-value time when we encounter the second instance of the |
I suspect there are many, many such cases where the potentially unsupported part of a value is a tiny fraction of it. This reminds me, in that case it should also support empty tokens, so one can do things like
I think the latter is far more flexible. Making it invalid in custom properties reduces its utility quite a lot. Also, any chance we could call it |
Sure, but it doesn't escale well. If you can put it in the middle of the value, it seems you can use it multiple times for different components, but that may not be well defined in general.
I think that would be a very confusing name. A clearer shorter name would be |
That's why we have IACVT.
That seems fine too. |
I originally proposed |
Edited in 5fc63f5, present in https://www.w3.org/TR/css-values-5/#first-valid |
When authors use
var()
, the UA has to assume that the property value is valid at parse time, and only check at computed-value time. If it ends up not being valid, it becomes invalid-at-computed-value-time, reverting to eitherinitial
orinherit
.This, unfortunately, loses us CSS's very useful forward-compatibility feature, where we can specify a property two or more times with different features and get the last one the UA supports. Instead we get the last one the UA supports or that has a
var()
in it, even if thevar()
-containing one uses features the UA ends up not understanding!Making this worse, more features are ending up requiring
var()
-like parsing - attr(), custom functions, etc - so this will only get more common. It would be pretty unfortunate to lose the forward-compatibility feature for a large swathe of CSS usage.An author can, of course, work around this with @supports. Unfortunately, it has the same separation/repetition/verbosity issues as MQs do, as explained in #5009.
So, related to #5009, perhaps we could have a "validity switch" in the same way? It'd be one of those "must be the whole value of the property" things, and using the same fallback logic as normal CSS, it would resolve to the last item the UA understands. It would just do it at computed-value time, so post-substitution.
So something like:
The text was updated successfully, but these errors were encountered: