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-variables] Are custom properties strings? #8533

Open
andruud opened this issue Mar 6, 2023 · 8 comments
Open

[css-variables] Are custom properties strings? #8533

andruud opened this issue Mar 6, 2023 · 8 comments
Labels
css-variables-1 Current Work

Comments

@andruud
Copy link
Member

andruud commented Mar 6, 2023

Is a custom property a token sequence that only serializes as the original string, or is it that original string? The difference can be seen in this example:

.container {
  --x:foo 1.00;
}
.container > div {
  @container style(--x:foo 1) {
    color: green;
  }
}

If custom properties are token sequences, this style query matches, but not if they are strings.

The point of serializing using the original string was to preserve "unknown stuff", and maintaining that idea probably means that we don't transform that unknown stuff before comparisons. Otherwise e.g. style(--uuid: 12345678-12e2-8d9b-a456-426614174000) would match --uuid: 12345678-1200-8d9b-a456-426614174000 (example stolen from https://drafts.csswg.org/css-variables/#serializing-custom-props, then modified).


Note that style(--x:1) would still match e.g. --x:1.00 according to the current plan in #8376, since the literal side matches <number>.

@tabatkins

@andruud andruud added the css-variables-1 Current Work label Mar 6, 2023
@tabatkins
Copy link
Member

I don't have a strong opinion on this. I'm fine with specifying they just stay as uninterpreted character sequences (rather than token sequences, specifically), so long as it's still clear and correctly implemented that comment insertion happens when you substitute things next to each other that would reparse differently. (Chrome still doesn't do this correctly when serializing, but does at least parse correctly; --x: 1; --y: var(--x)px; is correctly treated as two tokens, a number and an ident, rather than a length, even tho we'll serialize the computed value of --y as "1px" currently.)

(The reason Anders is filing this, btw, is that currently we preserve both the original string and the tokens for every custom property, and this is a noticeable memory burden on some sites like Amazon. It would be good to preserve only one of them, and since the original string is required to be preserved for author-observable behavior, dropping the tokens seems like the more viable one.)

@Loirooriol
Copy link
Contributor

Loirooriol commented Mar 7, 2023

https://w3c.github.io/csswg-drafts/css-variables/#serializing-custom-props

Specified values of custom properties must be serialized exactly as specified by the author. Simplifications that might occur in other properties, such as dropping comments, normalizing whitespace, reserializing numeric tokens from their value, etc., must not occur.

Computed values of custom properties must similarly be serialized exactly as specified by the author, save for the replacement of any var() functions.

So it seems to me that foo 1.00 and foo 1 are different.

Oh but good point about #8376, then I'm not sure what's best.

@tabatkins
Copy link
Member

In #8376 there's a suggestion that we just do the "looks numeric" check for = (along with the inequalities). : queries would do normal comparison.

So given --x: 1;, style(--x: 1.0) would be false but style(--x = 1.0) would be true.

@cdoublev
Copy link
Collaborator

Given --x: /* comment */ 1, style(--x: 1) would be true? Comments are removed with leading/trailing whitespaces when consuming a declaration (but not with CSSStyleDeclaration.setProperty() though).


I think this issue also applies to properties declared with arbitrary substitution values (eg. var()).

Given --x: 1.0 and opacity: var(--x), style(opacity: 1) would be false. Right?

@tabatkins
Copy link
Member

Given --x: /* comment */ 1, style(--x: 1) would be true? Comments are removed with leading/trailing whitespaces when consuming a declaration (but not with CSSStyleDeclaration.setProperty() though).

No, this is specifically not the case when serializing custom properties; see https://w3c.github.io/csswg-drafts/css-variables/#serializing-custom-props

Given --x: 1.0 and opacity: var(--x), style(opacity: 1) would be false. Right?

It's not yet clear if we'll allow style() queries on non-custom properties, but I can definitely say that if we do allow them, then no, that query would match. We'd at minimum base the comparison on the used-value serialization, which absolutely normalizes these things. This'll have nothing to do with whatever we do to custom properties.

@cdoublev
Copy link
Collaborator

cdoublev commented Mar 11, 2023

No, this is specifically not the case when serializing custom properties; see https://w3c.github.io/csswg-drafts/css-variables/#serializing-custom-props

Ok, so this is a browser issue.

style.cssText = '--x: /* comment */ 1 /* comment */'
style.cssText; // (Chrome) `--x:  1 ;` (FF) `--x: 1 /* comment */;`
style.setProperty('--x', '/* comment */ 1 /* comment */')
style.getPropertyValue('--x') // (Chrome) ` 1 ` (FF) `1 /* comment */`

Both may store comment representations with whitespace representations. FF does not remove trailing whitespaces (cf. #6484).

If style(--x: 1) should evaluate to false against --x: /* comment */ 1 /* comment */, I guess the original string representation might have to be created somehow when consuming a declaration.

@andruud
Copy link
Member Author

andruud commented Mar 11, 2023

No, this is specifically not the case when serializing custom properties; see https://w3c.github.io/csswg-drafts/css-variables/#serializing-custom-props

@cdoublev is right here. Comments are effectively not dropped within the value, but the bounds of the value are still determined by tokens, and comments do not produce tokens. Example 17 in Variables is not possible per css-syntax.

--x: /* comment */ 1 becomes <whitespace-token> <whitespace-token> <number-token>, then the whitespace tokens are stripped (consume a declaration), which leaves <number-token>, and the corresponding original string is then set from that.

Ok, so this is a browser issue.

Fully acknowledged, but it's also a spec issue. :-)

@cdoublev
Copy link
Collaborator

CSS Syntax 3 says (emphasize added):

Implementations may preserve the contents of comments and their location in the token stream

https://drafts.csswg.org/css-syntax-3/#serialization

But either implementations must preserve comments, or CSS Variables should not require serializing with comments.

I also note that serializing --x: 1 !important /**/ would produce --x: 1 !important (a new whitespace is added):

If the important flag is set, append " !important"

https://drafts.csswg.org/cssom-1/#serialize-a-css-declaration

I deleted my comment where I said that serializing exactly as specified only for <declaration-value> could help evaluating style(--y: /**/ var(--x)) to true when given --x: 1 and --y: var(--x). This would work only if not preserving comments and consecutive whitespaces.

Preserving the whole declaration string would also prevent --x: mix(75%; 0; 2) from matching style(--x: 2). But here again, this would require to change how custom property values serialize.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-variables-1 Current Work
4 participants