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-5] Invalidation of ident() #11424

Closed
bramus opened this issue Dec 31, 2024 · 7 comments
Closed

[css-values-5] Invalidation of ident() #11424

bramus opened this issue Dec 31, 2024 · 7 comments

Comments

@bramus
Copy link
Contributor

bramus commented Dec 31, 2024

This is a follow-up to #9141 which introduces ident(). Something that is not defined yet is what should happen when the input for ident() is invalid.

E.g. what happens if you do the following:

@property --length {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

.target {
  --length: 120px;
  anchor-name: ident("--anchor-" var(--length));
}

Because --length is a <length>, ident() can’t generate a valid <custom-ident>. I assume that in this case the declaration should become Invalid At Computed Value Time (IACVT) and the value should be considered to be unset.

However, we might also consider adding an extra argument to ident(), to allow a fallback value in case the constructed value is not a valid <custom-ident>.

The definition for ident() would then become the following:

<ident-fn> = ident(<ident-arg>+, <declaration-value>?);
<ident-arg> = <string> | <integer> | <ident>

I prefer this last version, as ident() then behaves similar to var() and attr(): when the input cannot be parsed into a <custom-ident> (or is the guaranteed invalid value) then the fallback value is used.

@LeaVerou
Copy link
Member

Yup, a fallback would be great, and the declaration is just invalid if no fallback is provided. I don't think IACVT needs to be explicitly mentioned here: just like any other function, it can be invalid at parse time if the arguments are known at parse time (e.g. ident(foo 12px).

Just let's make sure that we don't accidentally make things invalid that don't need to be. E.g. people should be able to use an integer <number> in there without having to explicitly get it through round().

@bramus
Copy link
Contributor Author

bramus commented Jan 22, 2025

Just let's make sure that we don't accidentally make things invalid that don't need to be. E.g. people should be able to use an integer <number> in there without having to explicitly get it through round().

That is/was discussed in #11551

@tabatkins
Copy link
Member

Something that is not defined yet is what should happen when the input for ident() is invalid.

Nope, that's perfectly defined already - the function is invalid because it doesn't match the specified grammar. (And because that happens due to var() substitution, it's IACVT rather than a parse failure.)

I don't think we really need a fallback here. In general, CSS functions don't guard against the possibility of some argument being invalid from a nonsense var() substitution. I'm not seeing anything special about ident() that would make it more necessary to add special handling.

@LeaVerou
Copy link
Member

Fair, one can always do a fallback with a separate variable:

--name: ident(--color- var(--color));
background: var(var(--name, --color-blue));

That said…

In general, CSS functions don't guard against the possibility of some argument being invalid from a nonsense var() substitution. I'm not seeing anything special about ident() that would make it more necessary to add special handling.

I've often needed fallbacks for calc(), so this may not be such a bad idea. But shouldn't be a blocker for ident().

@bramus
Copy link
Contributor Author

bramus commented Jan 24, 2025

In general, CSS functions don't guard against the possibility of some argument being invalid from a nonsense var() substitution.

attr() has something like that built in, no? attr(id type(<color>), blue) will fall back to blue if it turns out that the id attribute cannot be parsed into a <color>.

Fair, one can always do a fallback with a separate variable:

--name: ident(--color- var(--color));
background: var(var(--name, --color-blue));

I must say that the equivalent below is much easier to read (I also added the ", knowing they are not really necessary):

--color: red;
background: ident("--color-" var(--color), --color-blue);

You could also write the following, but that only holds up when the fallback starts with the same prefix

--color: red;
background: ident("--color-" var(--color, blue));
--color: red;
background: ident("--color-" var(--color), --default-bg-color);

@astearns astearns moved this from FTF agenda items to Friday morning in CSSWG January 2025 meeting Jan 28, 2025
@tabatkins
Copy link
Member

attr() has something like that built in, no?

attr(), like var(), is grabbing data from elsewhere, and that data might not exist - the custom property might not be defined (or is invalid), and the attribute might not exist. So having a fallback to apply in that case is an important bit of functionality, and is explicitly tied to the function's own behavior.

ident() has none of these issues. It computes its result entirely based on its provided arguments. Those arguments might themselves come from things like var() or attr(), but that's not part of ident()'s functionality or responsibility. Unless we decided that all CSS functions should start worrying about that and have the ability to specify a fallback (and, somehow, figured out how to make that grammatically unambiguous across all functions), I don't think we should special-case just the ident() function.

We also already have a function designed to handle exactly this case: first-valid().

background: first-valid( var(ident("--color-" var(--name))), var(--color-blue) );

This tries to parse background: var(ident("--color-" var(--name))), and if that fails for any reason, falls back to parsing background: var(--color-blue) instead.

@bramus
Copy link
Contributor Author

bramus commented Jan 30, 2025

Relying on first-valid() for this seems reasonable.

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

No branches or pull requests

3 participants