Skip to content

[css-properties-values-api] Substituting registered properties with var() #321

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

Closed
tim-loh opened this issue Oct 6, 2016 · 12 comments
Closed

Comments

@tim-loh
Copy link

tim-loh commented Oct 6, 2016

Are registered properties substituted as lists of tokens as per css-variables or as some sort of parsed representation? There are some cases where values can be parsed as different types so this affects whether the end value parses successfully, e.g.

--number: 0; height: var(--number);
--color: green; animation-name: var(--color);
--length-list: 5px 10px 20px; box-shadow: green var(--length-list);
--url: url(a.png); background-image: var(--url); /* <image> values can be <url> values so this should be valid */

For the last case, if the declarations are in separate files, do we resolve <url>/<image> types with a base URL from the sheet with variable declaration or the usage thereof? When these are not registered, it seems that we should use the "background-image" sheet (crbug.com/618165#c11) but doing this for a registered custom property means the custom property has a different computed value to where it's used.

@shans
Copy link
Contributor

shans commented Oct 6, 2016

(nit: as of TPAC, unregistered properties are substituted as strings, not lists of tokens).

It's interesting that there are two truthy-feeling principles opposed here:

  1. the computed value of a registered custom property shouldn't differ from the computed value part of a property that references that custom property (when the types align)
  2. registering a custom property shouldn't change its behavior

(1 means roughly that you shouldn't ever be able to have

--foo: [something];
property-with-type-matching-foo: var(--foo);

and getComputedStyle(el).getPropertyValue('--foo') !== getComputedStyle(el).getPropertyValue('property-with-type-matching-foo'); )

I don't really know what to do here. It does seem deeply weird for the variable to not resolve relative to the variable sheet when you know up-front that it is a url().

@tabatkins
Copy link
Member

(nit: as of TPAC, unregistered properties are substituted as strings, not lists of tokens).

No, this is inaccurate. (It would be crazy wrong taken literally as you said.) Untyped properties have their values preserved as literal strings, such that their serialization is identical to their input. They're definitely substituted as token streams, tho; otherwise you get very quirky parsing things where a single token can span across two var() substitutions.

Typed properties actually have typed values, tho, and get substituted as such. So your first and second examples should both be errors (height doesn't take numbers, animation-name doesn't take colors), your third should work as long as it's a correct number of lengths, and your fourth is fine.

The problem of url() resolution changing when the custom property switches from untyped to typed has already been brought up, and there's no good solution. I think the naive answer (typed properties resolve based on the sheet they show up in, just like any other property taking a url) is obviously correct; anything else means that typed custom properties have subtle (read: likely to cause bugs) differences from built-in properties. There's some potential bugs if people switch from untyped to typed, but that should hopefully go away as usage becomes greater.

@shans
Copy link
Contributor

shans commented Oct 6, 2016

I don't think the third example works without a lot of extra effort. Box shadow won't take a list of lengths in the typed OM, it'll take a special typed object.

Is there a reason we decided that typed properties can't fallback to untyped substitution? For example I think typed properties should still substitute into untyped custom properties? I remember we had a discussion around this back in Sydney in January but I don't remember the details.

@tabatkins
Copy link
Member

tabatkins commented Oct 6, 2016

Right, we're not talking about Typed OM here. What we've got instead is that, per the grammar of --length-list (presumably <length>+), we're gonna substitute in some number of lengths. We know that's three, so the value we end up with is <color> <length> <length> <length>, which is valid for box-shadow.

Is there a reason we decided that typed properties can't fallback to untyped substitution? For example I think typed properties should still substitute into untyped custom properties? I remember we had a discussion around this back in Sydney in January but I don't remember the details.

I don't recall. They should be able to sub into untyped properties; I imagine they'd get down-converted back into some equivalent token representation. This isn't well-specced.

@shans
Copy link
Contributor

shans commented Oct 6, 2016

Right, we're not talking about Typed OM here. What we've got instead is that, per the grammar of --length-list (presumably +), we're gonna substitute in some number of lengths. We know that's three, so the value we end up with is " ", which is valid for box-shadow.

We should maintain a correspondence between types in the Typed OM and the behavior of typed properties, anything else would be weird.

@tabatkins
Copy link
Member

tabatkins commented Oct 7, 2016

I'm confused. The deal with Typed OM is that we're designing things such that every property takes exactly one value, or a list of values; when the "value" is complex, we have a custom JS type to express it. That's a good design on the JS side, but has nothing to do with the CSS side of things, where properties take several values of various types. In CSS, box-shadow takes a color, a keyword, and some lengths.

@shans
Copy link
Contributor

shans commented Oct 7, 2016

It's fine to use typed custom properties to define part of a complex value, but I don't think we should do things like "let this generic list of lengths substitute into a place that needs a definite number of lengths". Instead we should have a type that represents that subcomponent, and use that.

@FremyCompany
Copy link
Contributor

FremyCompany commented Oct 15, 2016

Just to clarify, is this thread discussing whether giving a type of a property does:

(a) only cascades declarations that match and would animate according to the type provide, and eventually transition the property based on this type

or

(b) all of the above, plus that var() declarations referencing the property needs to accept any value that the referenced custom property could accept to be valid, otherwise it is considered invalid at parse time?

If that is the case: I remember my initial custom properties spec had something close to (b) to validate var(..., fallback) based on the fallback, but that has been rejected. I am not against validating the substitution at parse time, but if we validate the variable side for absolute correctness I think we also should validate the fallback for consistency, something we currently don't do.

As such, I would lean towards (a) given the current design of var().

@tabatkins
Copy link
Member

I think we also should validate the fallback for consistency, something we currently don't do.

Actually, that's an oversight; we just didn't think of that case. We should definitely validate the fallback against the registered grammar, and mark the var() as invalid when it fails (making the property invalid at parse-time).

@FremyCompany
Copy link
Contributor

Ok, in that case I have no opinion on the matter.

@jyc
Copy link
Contributor

jyc commented Feb 1, 2017

Is this intended for Level 1?

In Gecko, it would be straightforward to implement this sort of typed substitution for properties like height with simple grammars. However, implementation would be more tricky for properties with more complicated grammars like background-image. For example, disallowing things like linear-gradient(--number, ...) would require us to store some additional information.

@tabatkins
Copy link
Member

The original issue (should a property fail at parse-time if a typed custom property is used in a wrong way, per the property's grammar) is, I think, a no. I believe this falls out of our decision at the Seattle f2f (#354) that registering a custom property shouldn't require an immediate global re-parse. You can do wrong things to/with a typed custom property; it'll just cause a failure at computed-value time, like an untyped custom property with an incompatible value does.

The later issue (should we validate the var() fallback for consistency with the property's type) is something we probably should do. I'll move it to a separate issue for better tracking, and go ahead and close this one.

jyc added a commit to jyc/css-houdini-drafts that referenced this issue Jul 19, 2017
…ntax-checked at computed-value time, not parse time.

Clarify that the `syntax` field is used during computed-value time,
write in the section about calculation of computed values that
declarations can be found invalid at computed-value time, and update the
example which previously indicated syntax-checking at parse time.

Per Seattle resolution, as expressed in the following comments:

> The original issue (should a property fail at parse-time if a typed
> custom property is used in a wrong way, per the property's grammar) is,
> I think, a no. I believe this falls out of our decision at the Seattle
> f2f (w3c#354) that registering a custom property shouldn't require an
> immediate global re-parse. You can do wrong things to/with a typed
> custom property; it'll just cause a failure at computed-value time, like
> an untyped custom property with an incompatible value does.
>
> - w3c#321 (comment)

> Further clarification: per Seattle resolution, when using a typed
> property in a stylesheet, setting to an invalid value doesn't trigger
> fallback ...
>
> - w3c#354 (comment)
jyc added a commit to jyc/css-houdini-drafts that referenced this issue Jul 19, 2017
…ntax-checked at computed-value time, not parse time.

Clarify that the `syntax` field is used during computed-value time,
write in the section about calculation of computed values that
declarations can be found invalid at computed-value time, and update the
example which previously indicated syntax-checking at parse time.

Per Seattle resolution, as expressed in the following comments:

> The original issue (should a property fail at parse-time if a typed
> custom property is used in a wrong way, per the property's grammar) is,
> I think, a no. I believe this falls out of our decision at the Seattle
> f2f (w3c#354) that registering a custom property shouldn't require an
> immediate global re-parse. You can do wrong things to/with a typed
> custom property; it'll just cause a failure at computed-value time, like
> an untyped custom property with an incompatible value does.
>
> - w3c#321 (comment)

> Further clarification: per Seattle resolution, when using a typed
> property in a stylesheet, setting to an invalid value doesn't trigger
> fallback ...
>
> - w3c#354 (comment)
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

5 participants