Skip to content
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] Add valid-empty-like value (for CSS Custom Properties) #10441

Open
raphaelokon opened this issue Jun 13, 2024 · 17 comments
Open

[css-values] Add valid-empty-like value (for CSS Custom Properties) #10441

raphaelokon opened this issue Jun 13, 2024 · 17 comments

Comments

@raphaelokon
Copy link

raphaelokon commented Jun 13, 2024

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.

.meow {
  --foo: ; /* <- One whitespace character here. */

  color: var(--foo, hotpink) /* Resolves to `--foo` */
}

would become →

.meow {
  --foo: valid-empty; /* <- Explicitly mark missing value as valid. */
  
  color: var(--foo, hotpink) /* Resolves to `--foo` */
}

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.

@kizu
Copy link
Member

kizu commented Jun 13, 2024

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,).

@raphaelokon
Copy link
Author

raphaelokon commented Jun 13, 2024

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?

@raphaelokon raphaelokon changed the title [css-values] Add empty or null-like value (for CSS Custom Properties) [css-values] Add valid-empty-like value (for CSS Custom Properties) Jun 13, 2024
@LeaVerou
Copy link
Member

Or it could be syntactically distinct from other keywords somehow.

@raphaelokon
Copy link
Author

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.

@raphaelokon
Copy link
Author

@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: *;
}

@Loirooriol
Copy link
Contributor

I don't get it.

  • Why is it a hack to use a space?
  • Note you don't even need a space, --foo:; is valid too.
  • Would valid-empty just behave as a valid sequence of no tokens?
  • Why would this be useful?
  • If you dislike empty values, why not just use --foo: /*valid-empty*/;?

@raphaelokon
Copy link
Author

raphaelokon commented Jun 15, 2024

@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.

@kizu
Copy link
Member

kizu commented Jun 15, 2024

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:

A screenshot of chrome devtools showing a tooltip with an empty space (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.

@Loirooriol
Copy link
Contributor

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.

@LeaVerou
Copy link
Member

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.

@raphaelokon
Copy link
Author

@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 →

Screenie_2024-06-16-6oL6Jd5N@2x

I am also not able to manually set --bar: ; via the style inspector, but that may be a vendor issue.

@yisibl
Copy link
Contributor

yisibl commented Jun 17, 2024

@raphaelokon It looks like this is a bug in Chrome DevTools, please file a bug.

@raphaelokon
Copy link
Author

@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

Screenie_2024-06-17-C2ieNg5D@2x

@raphaelokon
Copy link
Author

raphaelokon commented Jun 17, 2024

There is also a mention of a no-value keyword in the inline conditional if() in #10064.

Edit: Add issue ref.

@Loirooriol
Copy link
Contributor

@raphaelokon
Copy link
Author

@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?

@Loirooriol
Copy link
Contributor

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 #6871 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants