Skip to content

[css-values-5] attr() and forwards compatible parsing #11035

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
fantasai opened this issue Oct 14, 2024 · 11 comments
Closed

[css-values-5] attr() and forwards compatible parsing #11035

fantasai opened this issue Oct 14, 2024 · 11 comments

Comments

@fantasai
Copy link
Collaborator

Now that attr()'s syntax expands to attr(<qname> <syntax>? [, <fallback-value>]?) where <syntax> has a fairly complex grammar, I was wondering if we need a divider between the two in case we ever want to expand the first argument?

(That said, I do like having the symmetry with var(), which delineates the variable as the variable before a comma, and the fallback value as everything after.)

@Loirooriol
Copy link
Contributor

Loirooriol commented Oct 14, 2024

Not just for forwards compat, but this could help for things like

display: attr(foo block | flex | grid)

As per the rules in https://drafts.csswg.org/css-values-4/#component-combinators, visually it looks like there are 3 alternatives: foo block, flex and grid. Sure, I could use this for clarity (assuming we allow it, seems @property doesn't):

display: attr(foo [block | flex | grid])

But separating the attr name from the syntax may be better.

@tabatkins
Copy link
Member

Yeah, I think just putting a comma there is what we need, similar to how we use commas to separate calculations (even when not strictly required for ambiguity, just because it makes things easier to read).

This does mean that we'll have to make the type required in order to supply a fallback (we can't otherwise tell a type and a fallback apart), but that's fine I think.

@andruud
Copy link
Member

andruud commented Oct 30, 2024

This does mean that we'll have to make the type required in order to supply a fallback (we can't otherwise tell a type and a fallback apart), but that's fine I think.

I don't think that's fine? Omitting the <syntax> part gives you the "substitute verbatim attribute" behavior that you can't get any other way (anymore). You'd be unable to provide a fallback for that case, then.

@tabatkins
Copy link
Member

Yeah, on review I realized the same thing, so I ended up keeping the <syntax> next to the attr name, not comma separated.

@andruud
Copy link
Member

andruud commented Nov 5, 2024

Is there a way forward here?

  1. Wrap the <syntax> part in something? (Brackets, like @Loirooriol suggested?)
  2. Add a way to explicltly ask for "substitute verbatim attribute", allowing us to add the comma?
  3. Close, no change?

@tabatkins
Copy link
Member

I think we should probably lean toward matching what @function is doing, with type(<syntax>). Clear what's happening, separated from surrounding grammar, consistent across features.

@andruud andruud added the Agenda+ label Nov 7, 2024
@tabatkins
Copy link
Member

In private conversation, @fantasai pointed out that, while this is nicely unambiguous, it's starting to get pretty heavy for simple cases. For example, to indicate that you want to parse the attribute as a number and interpret it as a px length, you'd write attr(foo type(<number px>)), where previously it was just attr(foo px).

She suggests going with the type() wrapper, but also still allowing a handful of keywords to indicate "simple" grammars. I suggest:

  • string for the "no interpretation, just the literal value as a string" case (currently indicated only by omitting the syntax arg)
  • value for "parse it as a single CSS component value" (automatically recognizing it as a length/angle/number/ident/etc)
  • px/em/etc for "parse it as a number, then give it that unit".

This gives us the best of both worlds for this simple case. And I don't think it should extend to other users of <syntax>, like custom functions or custom properties - string value isn't meaningful for values already written in CSS, value imposes no meaningful restrictions so it's very nearly just * anyway, and px/etc are not a use-case we want to encourage in other places.

@andruud
Copy link
Member

andruud commented Nov 12, 2024

That makes sense to me for attr(foo px) (etc). However:

  • Do we really need attr(foo string), when we could just omit the type?
  • Introducing attr(foo value) also seems unfortunate if it's "basically *"). type(*) will do here, it's just two chars longer than value, and avoids introducing another thing that's very nearly the same as an existing thing.
    • Alternatively, define value to be exactly the same as type(*).

px/etc are not a use-case we want to encourage in other places.

So this means we're dropping <number px>, right? Instead it's just px, specific to the attr() grammar.

@tabatkins
Copy link
Member

  • Yes, in general I'm somewhat opposed to behaviors that are only indicated by a lack of something, when we can avoid it. Having a default is good, but it's much easier to define/reference/teach when there's an actual value that produces the behavior.
  • You're right, value doesn't actually add anything over type(*). So yeah, I think just using type(*) is fine.
  • Dropping <number px> would knock out some cases that could potentially be useful (accepting an attribute which can be either a percentage or a number that should be interpreted as px), but I think that's okay now that we have such an easy way to write the simple case. Previously, even the simple case was hard (requiring a wrapping calc()), so addressing the complex case at the same time as making the simple case easier was worthwhile. So yeah, I think we can drop <number px> unless/until it's requested.

So, the exact proposal is that the parsing specifier for attr() can be either:

  • type(<syntax>), allowing the full range of <syntax> values and resembling custom functions' grammar.
  • string, meaning "take the value of the attribute exactly as written", aka the current behavior. (This is also the default if omitted.)
  • px/etc (all defined CSS units), meaning "parse as a number, and then give it that unit". Aka, attr(foo px) is identical in behavior to calc(attr(foo type(<number>)) * 1px).

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-values-5] attr() and forwards compatible parsing, and agreed to the following:

  • RESOLVED: Accept proposal to use type(<syntax>), add string, and add units as keywords.
The full IRC log of that discussion <fantasai> Scribenick: fantasai
<fantasai> TabAtkins: We switched attr() to use type definition syntax, similar to variables
<fantasai> TabAtkins: But working through that, we lost some abilities
<fantasai> TabAtkins: for example, saying the attr is a number representing px values
<fantasai> TabAtkins: It started to get too complicated for common cases
<fantasai> TabAtkins: For grammar ambiguity reasons, we suggest to wrap in type() function
<fantasai> TabAtkins: and end up with a lot for simple cases.
<fantasai> TabAtkins: Suggestion is to keep the <syntax> argument, but wrapped in type()
<fantasai> TabAtkins: but for two cases we have an easier way to specify
<fantasai> TabAtkins: for default behavior of treating attr value as a string, we introduce a keyword (string) so you can say so explicitly
<fantasai> TabAtkins: and secondly, add all units as keywords, which parse as a number and attach that unit
<fantasai> TabAtkins: this does slightly reduce the power of the syntax compared to before, since can't mix this behavior with other values
<fantasai> TabAtkins: but I think it's OK, not a high-value use case right now; can evaluate later or add to <syntax> production
<fantasai> TabAtkins: but instead of type(<number px>) can just write px, much simpler
<fantasai> TabAtkins: so proposal is
<fantasai> 1. Add type() wrapper around <syntax>
<Rossen0> q?
<kizu> +1 to the proposal
<fantasai> 2. Introduce string keyword for explicitly indicating string parsing
<chrishtr> +1
<fantasai> 3. Add all units to attach to a <number>
<lea> I don't understand the proposed options
<TabAtkins> attr(foo type(<length>))
<TabAtkins> attr(foo string) (deffault behavior)
<fantasai> attr(attributename [ type(<syntax>) | string | <unit> ], fallback)
<TabAtkins> attr(foo type(*))
<fantasai> lea: can you parse in a token stream?
<fantasai> TabAtkins: yes, use * just like in custom properties
<ydaniv> +1
<fantasai> lea: what's without the proposal?
<fantasai> attr(attributename <syntax>, fallback)
<fantasai> TabAtkins: wanted to wrap type() because <syntax> would make parsing complicated if we add anything in the future
<fantasai> lea: could we use keyword instead of type()?
<florian> wfm
<fantasai> TabAtkins: using type() because that's what we do in custom functions
<fantasai> TabAtkins: thought about using 'as' but consistency is good
<fantasai> lea: no way to use 'as' in functions? presumably want to know where the syntax terminates
<fantasai> TabAtkins: yes, and in some cases if you want to accept several keywords...
<fantasai> TabAtkins: having type() wrapper makes it clearer
<lea> +1
<TabAtkins> attr(foo type(one | two | three))
<oriol> +1
<fantasai> wfm
<fantasai> Rossen0: Anyone else? Any objections?
<fantasai> RESOLVED: Accept proposal to use type(<syntax>), add string, and add units as keywords.

@tabatkins
Copy link
Member

Closing, as the WG resolution successfully resolved this. The <syntax> production is now wrapped in type(), so it can't cause problems for future development (and doesn't need another separating comma, either).

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Nov 14, 2024
Recent spec resolution [0] introduced the following changes to attr
type syntax:
1. Add type() wrapper around <syntax>
2. Introduce string keyword for explicitly indicating string parsing
3. Add dimension units to attach to a <number>

[0] w3c/csswg-drafts#11035 (comment)

Bug: 369858674, 40320391
Change-Id: I04356918cceaf8445fcdfd896bf3567b2cce792f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6020597
Reviewed-by: Anders Hartvoll Ruud <[email protected]>
Commit-Queue: Munira Tursunova <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1383003}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Nov 14, 2024
Recent spec resolution [0] introduced the following changes to attr
type syntax:
1. Add type() wrapper around <syntax>
2. Introduce string keyword for explicitly indicating string parsing
3. Add dimension units to attach to a <number>

[0] w3c/csswg-drafts#11035 (comment)

Bug: 369858674, 40320391
Change-Id: I04356918cceaf8445fcdfd896bf3567b2cce792f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6020597
Reviewed-by: Anders Hartvoll Ruud <[email protected]>
Commit-Queue: Munira Tursunova <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1383003}
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Nov 16, 2024
… changes, a=testonly

Automatic update from web-platform-tests
Change attr type syntax with recent spec changes

Recent spec resolution [0] introduced the following changes to attr
type syntax:
1. Add type() wrapper around <syntax>
2. Introduce string keyword for explicitly indicating string parsing
3. Add dimension units to attach to a <number>

[0] w3c/csswg-drafts#11035 (comment)

Bug: 369858674, 40320391
Change-Id: I04356918cceaf8445fcdfd896bf3567b2cce792f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6020597
Reviewed-by: Anders Hartvoll Ruud <[email protected]>
Commit-Queue: Munira Tursunova <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1383003}

--

wpt-commits: 51ac948eb3f2859dab874d2103c9e14cf4cfd5b5
wpt-pr: 49173
jamienicol pushed a commit to jamienicol/gecko that referenced this issue Nov 18, 2024
… changes, a=testonly

Automatic update from web-platform-tests
Change attr type syntax with recent spec changes

Recent spec resolution [0] introduced the following changes to attr
type syntax:
1. Add type() wrapper around <syntax>
2. Introduce string keyword for explicitly indicating string parsing
3. Add dimension units to attach to a <number>

[0] w3c/csswg-drafts#11035 (comment)

Bug: 369858674, 40320391
Change-Id: I04356918cceaf8445fcdfd896bf3567b2cce792f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6020597
Reviewed-by: Anders Hartvoll Ruud <[email protected]>
Commit-Queue: Munira Tursunova <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1383003}

--

wpt-commits: 51ac948eb3f2859dab874d2103c9e14cf4cfd5b5
wpt-pr: 49173
i3roly pushed a commit to i3roly/firefox-dynasty that referenced this issue Nov 20, 2024
… changes, a=testonly

Automatic update from web-platform-tests
Change attr type syntax with recent spec changes

Recent spec resolution [0] introduced the following changes to attr
type syntax:
1. Add type() wrapper around <syntax>
2. Introduce string keyword for explicitly indicating string parsing
3. Add dimension units to attach to a <number>

[0] w3c/csswg-drafts#11035 (comment)

Bug: 369858674, 40320391
Change-Id: I04356918cceaf8445fcdfd896bf3567b2cce792f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6020597
Reviewed-by: Anders Hartvoll Ruud <[email protected]>
Commit-Queue: Munira Tursunova <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1383003}

--

wpt-commits: 51ac948eb3f2859dab874d2103c9e14cf4cfd5b5
wpt-pr: 49173
SebastianZ added a commit to SebastianZ/csswg-drafts that referenced this issue Feb 19, 2025
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