Open raphaelokon opened 5 months ago
I just want to clarify that for
--foo: empty; /* <- Declarative absence of a value. */ color: var(--foo, hotpink) /* Resolves to `hotpink` */
It will still resolve to --foo
, just explicitly.
A good use case outside the space toggles is when we want to have a “placeholder” of sorts inside a shorthand. I wrote a post with one example like that here: https://blog.kizu.dev/space-toggle-placeholders/
Re: the name itself, as this will be a CSS-wide keyword, and essentially allowed anywhere, we need something less generic than empty
. Maybe something like guaranteed-valid
, valid-empty
? empty-placeholder
? Something else?
The goal of the value is to make the declarations like --foo: guaranteed-valid
or var(--foo, guaranteed-valid)
more explicit and easy to understand compared to --foo: ;
or var(--foo,)
.
Ah, now I see, I missed this detail. In this regard I really like the valid-empty
keyword. I’ll edit it If that is okay for you?
Or it could be syntactically distinct from other keywords somehow.
Or it could be syntactically distinct from other keywords somehow.
@LeaVerou This one is interesting as well and opens other possibilities. Any ideas what would be syntactically possible?
What I like about @kizu’s suggestion valid-empty
(as opposed to guaranteed-valid
) is that the spec describes values being guaranteed-invalid
and not the value itself. In this understanding the --foo: ;
and --foo: valid-empty;
keyword would be a guaranteed-valid
values.
@LeaVerou I’ve been thinking about other syntaxes as well. We probably have to define if there are use-cases outside of custom props for this keyword.
Some high-level ideas (not happy with them) working around CSS’s case-insensitivity (I still like the explicit nature of valid-empty
):
.meow {
--foo: ();
--baz: !valid;
--bar: *;
}
I don't get it.
--foo:;
is valid too.valid-empty
just behave as a valid sequence of no tokens?--foo: /*valid-empty*/;
?@Loirooriol
tl;dr Make a valid empty custom prop (or a space variable placeholder for that matter) more readable and explicit.
Why is it a hack to use a space?
That is the name you can find it under and the CSS community refers to when using it.
Note you don't even need a space, --foo:; is valid too.
Aye, I know. That is true, but that does not make the readability issue any better.
Would valid-empty just behave as a valid sequence of no tokens?
I am not sure I can answer this. But in my opinion valid-empty
would be a CSS-wide keyword.
Why would this be useful?
To me having an explicit keyword to set the value of a custom property to guaranteed-valid
would be consistent in how you manually reset a custom property to guaranteed-invalid
by using initial
keyword.
If you dislike empty values, why not just use --foo: /valid-empty/;?
I am not disliking it, it is more to have an explicit keyword. But having comments looks even more hackier to me.
EDIT: Fix typo.
If I recall correctly, at some point --foo:;
(and var(--foo,)
— without a space) was not valid. Right now it is, yes.
My main argument is learnability and discoverability: when you see something like this in your code or devtools:
(there is a tooltip that looks empty)
You just see an empty value, which does not tell you anything. You could put the /* empty */
in the variable definition, but used value somewhere else won't have it. And then CSS minifiers would likely remove the comment, making the source less undersrandable again.
When you discover something like that in the wild, and you're an author who does not know about this valid empty value, how would you search for it? A query like “css empty value” won't help, but “css empty variable value” would, but not everyone is good at search, sadly. It is much easier to look for something like “css valid-empty” when you know the keyword.
CSS-wide keywords should work everywhere, would you accept color: valid-empty
?
I also don't get why you would want color: var(--foo, hotpink)
to be IACVT instead of using the fallback.
And an empty tooltip in devtools doesn't seem cunfusing to me, if the value is empty.
FWIW I completely agree with @Loirooriol: I think an actual empty value is the most self-explanatory value we could ever come up with. It’s literally WYSIWYG!
@kizu It seems that it's the empty tooltip that's the problem here, not the syntax. Dev tools could easily show something like "(Empty value)" to make this clear.
@Loirooriol
CSS-wide keywords should work everywhere, would you accept color: valid-empty?
That is a good point tbh. Maybe only scoping the value keyword to custom properties --
and var()
as in --foo: valid-empty;
or var(--foo, valid-empty)
. Maybe could help with #9847 as well.
I also don't get why you would want color: var(--foo, hotpink) to be IACVT instead of using the fallback.
Just to show the same behavior of an empty value string and valid-empty
here, no practical reason.
@LeaVerou @kizu Regarding dev tools, I get this tooltip behavior →
I am also not able to manually set --bar: ;
via the style inspector, but that may be a vendor issue.
@raphaelokon It looks like this is a bug in Chrome DevTools, please file a bug.
@Loirooriol Another thing I noticed when registering a custom property with CSS and JS when defining an intitial-value
with a single space →
@property --foo {
syntax: "*";
inherits: false;
initial-value: ; /* Single space here …*/
}
window.CSS.registerProperty({
name: "--meow",
syntax: "*",
inherits: false,
initialValue: " ", /* Single space here …*/
});
When getting the value of the custom props we get different value behavior.
const styles = window.getComputedStyle(document.documentElement);
console.log(styles.getPropertyValue("--foo")?.length); // => 0
console.log(styles.getPropertyValue("--meow")?.length); // → 1
There is also a mention of a no-value
keyword in the inline conditional if()
in #10064.
Edit: Add issue ref.
@raphaelokon That's a bug. https://drafts.css-houdini.org/css-properties-values-api/#the-registerproperty-function
parse initialValue as a
<declaration-value>
.
@yisibl I’ll file a Chrome DevTools bug.
@Loirooriol Is there already a bug filed for it in CSS Houdini or should I file one?
I meant implementation bug. But actually not, it's just parse a declaration what trims whitespace. But I do think <declaration-value>
should trim too as said in https://github.com/w3c/csswg-drafts/issues/6871#issuecomment-990127688
But having comments looks even more hackier to me
If you don't want to use a "hacky" space/comment everywhere, you could also use an auxiliary variable, with an explanation of what's going on, and then just let all the consumers reference it.
:root {
/* This sets `--valid-empty` to an empty value, this allows setting `--foo: var(--valid-empty)`
so that `var(--foo, hotpink)` resolves to an empty value instead of falling back to `hotpink`
or becoming invalid at computed-value time. */
--valid-empty: ;
}
.meow {
--foo: var(--valid-empty); /* <- Explicitly mark missing value as valid. */
color: var(--foo, hotpink); /* Resolves to `--foo` */
}
There was a brief conversation (I think between @kizu and @andruud) I participated during CSS Day regarding a declarative keyword to mark the guaranteed absence of a value for a custom property to avoid the
space toggle hack
, e.g.would become →
I think that the inline conditional or
if()
spec #10064 by @LeaVerou (which was just marked as resolved 🎉) may fix a lot of use-cases around this, but there maybe still be use-cases for a declarative empty value.EDIT: Change the semantic of the keyword and make it less generic by naming it
valid-empty
re comment.