[csswg-drafts] [css-values-4] Switch advanced attr() to being var()-like (#4482)

tabatkins has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-values-4] Switch advanced attr() to being var()-like ==
Currently, the "advanced" attr() functionality that lets you specify a type to parse as and a fallback to use is specified to require treating the attr() as the specified type during parse time. That is, `width: attr(foo color);` must be rejected as invalid at parse time, because `width` doesn't take `<color>` arguments.

This definition predates the introduction of var() and its specifying of how to handle values that are invalid when substituted in; at the time attr() was written, "invalid at computed-value time" didn't exist, so the only way we knew how to handle this sort of thing was to eagerly typecheck and specify defaults.

One of our Chrome engineers (@xiaochengh) is looking into implementing advanced attr(), and reviewing it with them, it looks like implementing the function as specified will be *quite* complicated; handling its type-checking will require additions to *every* manually-parsed grammar in the browser.

However, switching attr() over to acting like var() should be *much* simpler. All the machinery for handling something substituted at computed value time, and possibly being iacvt, already exists and can be leaned on pretty easily for all properties.

(The type argument does still have value here. For one, it's a switch that dictates whether you take the attribute value as a literal string, or CSS-tokenize it. For two, it advertises to later stylesheet readers what's expected. For three, it helps you guard against garbage in attributes, which is more likely than garbage in variables, and use a fallback instead. For four, the `px`/etc values are useful for parsing plain numeric attributes, which are common in XML languages, into the appropriate CSS unit, without needing calc() shenanigans.)


So the proposal, in full:

* drop the spec text that gives attr() a specific type. Instead, using attr() makes the property always valid at parse time, like var() does.
 * possibly only do this when you provide a type: an untyped attr() is still string-only and only usable in 'content'; to use a string outside of 'content' explicitly say `attr(foo string)`.
* at computed-value time, attr() retrieves the attribute value and parses it according to the provided type argument. If it fails to parse, use the fallback value instead; if there's no fallback, use the guaranteed-invalid value instead.
* substitute the attr into the property, using the same rules as var(). Just like var(), you then grammar-check the property, and if it fails, it's invalid at computed-value time (iacvt).
* add a `tokens` type (or maybe spell it `*`) that does no parsing, but does still tokenize the value and substitute it accordingly (rather than substituting it as a `<string>`), to handle more complicated cases, now that we're free from the tyranny of parse-time type-checking. This type will only trigger fallback if the attribute isn't present at all.
* remove the "default value" definitions for each type; they were necessary before we had iacvt as a concept, but not anymore. If you want to provide a default value, that's what the fallback is for.


(Note for the Agenda+; I won't be attending the Nov 6th call, so please schedule it for the Nov 13th call instead.)

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/4482 using your GitHub account

Received on Monday, 4 November 2019 22:00:23 UTC