Skip to content

[css-properties-values] CSSOM for multi-name and shorthand @property #14227

Open

Description

@LeaVerou

In #7523 (comment) we resolved to adopt a comma-separated syntax for <custom-property-name> to support registering multiple properties that share the same descriptors in one go.

However, we do not seem to have consensus on the best CSSOM to represent this.

Opening this so we can discuss without clobbering the shorthand syntax discussed in #7523, though the design should also take it into account.

Discussion

Requirements

Nice to haves

  • Roundtripping. Plenty of places where CSS doesn't roundtrip, so not a biggie if it doesn't, but it's nice if it does.
  • Authors should not need to parse property names and split by commas. This will get very awkward once [css-properties-values-api] Shorthand for custom property declaration #7523 is introduced, as they'll now need to parse a full blown microsyntax.
  • CSSPropertyRule.prototype.name is read-only so we don't need to answer the question "how does the setter behave?". That said, it would be nice if the design did not actively get in the way of making it writable later.

Options

Option 1: Expand to multiple CSSPropertyRule rules at parse time

No CSSPropertyRule changes. The rule just expands to multiple CSSPropertyRule rules at parse time.

Pros:

  • No CSSOM changes
  • Supports almost any future syntax
  • Authors don't need to parse any microsyntax
  • Backwards compatible with existing consumers

Cons:

  • No roundtripping
  • Making name writable later would be hard
  • insertRule() can insert multiple rules, which is weird

Option 2: name/names

This includes:

  1. name includes the full comma-separated list, no other change
  2. name includes the full comma-separated list, names as a FrozenArray
  3. name is empty when multiple names, names as a FrozenArray

Pros:

  • Serialization roundtrips

Cons:

  • All of these special case the name fanout, unclear how this expands to the syntax shorthand. In theory we could add plural versions of all descriptors as shorthands are added (syntaxes etc), but we need to keep multiple arrays in sync, which is awkward
  • For 2.1: Authors need to do their own parsing, which will get even more complex with the shorthand expansions

Option 3: Nested CSSPropertyRule

CSSPropertyRule gains a cssRules property which is a CSSPropertyRule[]. Its properties represent base values as specified in the actual rule, but child rules can override them.

Single-property usage is backwards compatible, consumers need to be updated to read multi-property rules correctly.

Pros:

  • Most faithful representation, objects correspond exactly to what was written
  • Roundtrips correctly
  • Scales better to future syntax extensions like shorthand types, nesting etc
  • Even supports a future writable name — it would just generate cssRules.

Cons:

  • Biggest lift, incompatible with code consuming the existing schema
  • Requires additional design decisions for every single descriptor on the root object
    • What would name be? Empty? A comma-separated list? The first name?
    • What would syntax be once we have the shorthand syntax? Empty? A union of all? The first one?
    • etc

I’m moderately strongly against 2, but I'm fine with 1 or 3.

I originally recommended 1 as I think it would be unfortunate to gate this feature on a big CSSOM change, but 3 is the "proper" way, and can scale to cover a lot of future expansion.

Activity

  1. emilio commented on Jul 25, 2026

    @emilio
    Collaborator

    There are other options, like 2 but multiple names return empty for name. That's somewhat similar to what we did for @container when we added multiple conditions: #13635. We could do something like that? It's pretty simple. Not sure what the 'authors need to do their own parsing' concern is about?

    Potential writable names and so on are also not a concern, IMO. These interfaces should be kept read-only unless there's extremely good reason to do otherwise, we resolved on making the OM as readonly as possible quite a while ago.

  2. LeaVerou commented on Jul 26, 2026

    @LeaVerou
    MemberAuthor

    There are other options, like 2 but multiple names return empty for name.

    I added this to the post. Is this an example or do you have more options in mind?

    That's somewhat similar to what we did for @container when we added multiple conditions: #13635. We could do something like that? It's pretty simple.

    That works for @container because the prelude is a separate thing from the contents, similarly to a media query or even a regular CSS rule. Here once we add the shorthand syntax, the prelude is basically setting descriptors that normally live in the rule itself (which also brings up a question about serialization…).

    Not sure what the 'authors need to do their own parsing' concern is about?

    It was specific to the option where name holds the whole thing. Clarified in the OP.

    Potential writable names and so on are also not a concern, IMO. These interfaces should be kept read-only unless there's extremely good reason to do otherwise, we resolved on making the OM as readonly as possible quite a while ago.

    Yes, I don't see it happening anytime soon, but still good to keep options open. We've reversed many things we said we'd never do. It's only a nice-to-have, and I'd give it pretty low weight.

  3. changed the title [-][css-properties-values] CSSOM for multi-name `@property`[/-] on Jul 26, 2026
  4. Loirooriol commented on Jul 26, 2026

    @Loirooriol
    Contributor

    unclear how this expands to the syntax shorthand

    What do you mean with the syntax shorthand?

  5. LeaVerou commented on Jul 26, 2026

    @LeaVerou
    MemberAuthor

    unclear how this expands to the syntax shorthand

    What do you mean with the syntax shorthand?

    The @property --name <syntax>: initial-value, --name2 <syntax2>: initial-value2, ... shorthand discussed in #7523

  6. Loirooriol commented on Jul 26, 2026

    @Loirooriol
    Contributor

    Isn't it the other way round, that the shorthand statement syntax would expand to the normal rule syntax? So I'm not sure why it would be a concern here. I'm not getting the "plural versions of all descriptors" thing.

  7. moved this from Agenda+ FTF to Thursday Afternoon in CSSWG summer 2026 meeting agendaon Aug 1, 2026
  8. css-meeting-bot commented on Aug 6, 2026

    @css-meeting-bot
    Member

    The CSS Working Group just discussed [css-properties-values] CSSOM for multi-name and shorthand `@property` , and agreed to the following:

    • RESOLVED: if single @property has multiple names, it will be represented in CSSOM as a single object with a `names` array and not expand into multiple objects and return empty string for the `name` in that case
    The full IRC log of that discussion <keithamus> q?
    <keithamus> q+
    <lea> lea: We already have a resolution to support a, separated syntax for @Property, but it was never clarified what the CSSOM side of things would look like.
    <TabAtkins> we resolved to support `@property --foo, --bar { syntax: "<integer>"; initial: 1; }`
    <lea> lea: Also, there are proposals for potentially wild carding at property. And while I don't think it would be a productive use of time to discuss whether we want to do that right now, it would be good to not shoot ourselves in the foot for things like that in the future. And whatever CSSOM shape we end up with also supports expansions like that.
    <TabAtkins> we also want to support `@property --foo <integer>: 1;` (aka borrowing the @function argument syntax)
    <lea> lea: There are multiple proposals in the thread about what this might look like.The simplest one is probably to expand to multiple CSSPropertyRule objects at parse time but that has several issues.
    <lea> lea: The more flexible one is probably a nesting model where you have children of a CSSPropertyRule, but that's the biggest delta and the most complex.
    <astearns> q+
    <oriol> q+
    <lea> lea: And another one might be to add a names property and then name is either empty or a serialized version of all names. The problem is that this does not expand to the shorthand syntax.
    <bramus> ChrisL: Do you want to have a breakout with yourself?
    <lea> lea: It is a very important bit I forgot to mention in the beginning when I was introducing the issue. This is not about wildcarding. Forget wild carding. This is about the shorthand syntax we're thinking of introducing. Like not just the shorthand syntax where we add short versions of all the descriptors
    <astearns> s/potentially wild carding/potentially shorthanding/
    <lea> lea: For example `@property ---foo <length>, --bar <number>`
    <lea> lea: and a `names` key would not actually help with that.
    <TabAtkins> q+
    <lea> lea: I mean you could have plural properties of every possible descriptor and then have parallel arrays and associate them that way but then it becomes kind of annoying.
    <bramus> astearns: we have most of the context, lets go to queueu
    <bramus> keithamus: inhertiance is required in @prpoerty?
    <astearns> ack keithamus
    <bramus> lea: not anymore
    <bramus> keithamus: point of duplication: could be 2 syntaxes: `@property dashed-ident dashed-ident dashed-ident { … } ` and coul dhave one with just prelude
    <emilio> q+
    <lea> `@property ---foo <length>, --bar <number>, --color <transparent>: transparent`
    <astearns> q-
    <bramus> … and you could pick and choose based on similarly syntaxed properties or multiple props all iwht different syntaxes
    <astearns> ack oriol
    <bramus> oriol: think we should go with option 2
    <bramus> … (order in the issue)
    <bramus> … so adding `names`
    <bramus> … list of value’s names
    <bramus> … if you have more htan one, and access singular you get empy string
    <bramus> … consisten with @container
    <bramus> … arguments about new proposal shorthand, still have not discussed it nor resolutions
    <keithamus> q?
    <bramus> … tend to think its a bit ugly
    <bramus> … but could be sth to consider once we add it
    <bramus> … think we have resolutin for multiple propertiesin at-rule
    <bramus> … and go for more straightforward soolution that is consistent with existing features
    <keithamus> q+
    <bramus> TabAtkins: did oriol’s comment about multiple syntaxes and efault values?
    <astearns> ack TabAtkins
    <bramus> oriol: we have not discussed that yet … so shoul dnot decide on sth we have not discussed yet
    <bramus> TabAtkins: part of reason for discussing here
    <bramus> … these 2 do line up together
    <bramus> … my preferred one is to do what oriol is saying but also allow really shorthand bu t not let that be multiple
    <bramus> … you can say `@property --foo, --bar, --baz {}`
    <bramus> … and reflect that as `.names`
    <bramus> … or could say `@property --foo <integer>: 1` and would singular only
    <bramus> … turn into normal singular @Property rule
    <bramus> … main reason for comma separte names is that rest of block is lots of stuff to repeat
    <bramus> … only thing you save from comma separteing the inline form you are not having to type `@property`
    <bramus> … again.
    <bramus> … and the other thing is if you do allow the inline form to become comma=separted, you ahve to be careful about cmmas in the value (like function definitions, use {} iof necessary)
    <bramus> … but dont want authors to be ?? of that
    <kbabbitt> s/??/cognizant/
    <astearns> s/??/cognizant/
    <keithamus> q+
    <lea> me I don't understand what TabAtkins is proposing
    <bramus> … so my preferred is to make inline registariotn be singular, the multiple be just names, and we use option 2 for CSSOM (like oriol)
    <bramus> +1
    <emilio> q+
    <emilio> +1*
    <bramus> TabAtkins: (reexplains singular form)
    <bramus> lea: (has concerns)
    <bramus> astearns: is this separable?
    <bramus> TabAtkins: if we are OK with what I said as a possibliyt, then it doesn taffect OM for multi name case. if its not, then it needs to be part of this
    <bramus> emilio: disagree
    <lea> q?
    <astearns> ack emilio
    <bramus> … dont disagree with tab’s proposal
    <lea> q+
    <bramus> … we also have precedent for separate interface for block vs statement version of a rule
    <bramus> TabAtkins: thats different
    <bramus> emilio: my point is that i dont think we paint ourselves into a corner
    <astearns> qq+
    <TabAtkins> (block layer puts rules in a layer; statement layer just declares layer names; they're semantically different)
    <bramus> … would be a bit weird to serialize the inline form as the block form
    <bramus> … its fine but point is that we ar enot that constrained as we think we are
    <bramus> … and should resolve to what oriol said
    <bramus> TabAtkins: you’re right
    <TabAtkins> emilio's right, there are other approaches we can do
    <bramus> emilio: and if we decide on the shorthand being not compat, we can add an @Property statement rule in the OM and thats fine
    <bramus> JohnJansen: so did you agree with tab?
    <kbabbitt> +1 emilio
    <bramus> emilio: with the thing for this issue yes, not to resolve on all details of shorthand
    <bramus> +1 to emilio
    <bramus> TabAtkins: fine with that
    <astearns> ack astearns
    <Zakim> astearns, you wanted to react to emilio
    <astearns> ack keithamus
    <bramus> keithamus: clarifiying question about inherits
    <bramus> … what is default?
    <bramus> TabAtkins: need to check the minutes
    <bramus> … defaults to true (similar to untyped)
    <bramus> keithamus: so syntax is also omissable
    <bramus> TabAtkins: and defaults to *
    <astearns> ack lea
    <bramus> astearns: so we have arrive at conclusion that syntax is separable from this OM issue
    <bramus> TabAtkins: yes
    <astearns> s/arrive at/arrived at the/
    <bramus> lea: think once you ahve multiple names and once you have shorthand, combining two is what authors will ask for, so dont think we should separate
    <bramus> emilio: that is tangentional to this issue
    <bramus> … can decided anything we want for that
    <bramus> … dont need to resolve on not allowing that
    <bramus> … what tab said with commas for example, that is tangentional
    <bramus> astearns: which is why I wanted to separate it
    <bramus> … to only focu son OM
    <bramus> lea: but the OM needs to suppport both
    <bramus> emilio: can introduce new thing for @proeprty statement if we really need to
    <bramus> TabAtkins: can reflect them if needed
    <bramus> lea: but its a different syntax
    <bramus> … would be fine with having different syntax for plural
    <bramus> TabAtkins: name of interface would not trip up folks
    <bramus> astearns: think i have heard concensus for option 2 inthe issue
    <bramus> … ccssom with .names array
    <bramus> emilio: if we wanted to keep CSSPropertyRule we could and stash more stuff in OM but dont see how that is a problem
    <bramus> … like names, initialvalues, etc
    <bramus> … in a way that does not risk compat issues
    <bramus> … like name returning emptry string
    <lea> https://www.irccloud.com/pastebin/QE75JJNy/
    <lea> lea: a lot of value in combining, e.g. inside the rule these are the defaults, this can be very powerful
    <bramus> emilio: I thkn you are talking about some sort o fthird syntax; both a block and stuff in prelude, which is another thing
    <bramus> lea: that was plan all along?
    <bramus> emilio: I thought about a statement
    <bramus> … dont think we are blocked on that for this
    <lea> `@property --color-accent: red, --color-canvas: white { syntax: "<color>"; }`
    <TabAtkins> The "inline" version is just `@property --foo <integer> 1;`, a statement with no block
    <bramus> astearns: so can we resolve on option 2 in issue?
    <TabAtkins> literally "exactly the syntax of a function argument"
    <bramus> emilio: with name returning emptry string when there are multi-names
    <bramus> lea: I think option 2 is terrible, but dont feel strongly enough to object
    <bramus> … in the grand scheme of things
    <bramus> astearns: we have to pick something
    <bramus> … should we take back to issue?
    <emilio> `@property --foo, --bar {}` returns `names = ["--foo", "--bar"], name = ""`
    <bramus> lea: if it is just me, then no/.
    <bramus> astearns: if single @Property has multiple names, it will be represented in CSSOM as a single object with a `names` array and not expand into multiple objects and return empty string for the `name` in that case
    <bramus> lea: so shorthand form is not part of resolution
    <bramus> TabAtkins: correct
    <bramus> keithamus: would names be populated if it has a single name?
    <bramus> emilio: yes, 1 length array
    <bramus> astearns: objections?
    <bramus> PROPOSED: if single @Property has multiple names, it will be represented in CSSOM as a single object with a `names` array and not expand into multiple objects and return empty string for the `name` in that case
    <tuankiet65> +1
    <TabAtkins> +1
    <keithamus> +1
    <kbabbitt> +1
    <florian> +1
    <fantasai> +1 but clarify that names exists even if only one name
    <bramus> RESOLVED: if single @Property has multiple names, it will be represented in CSSOM as a single object with a `names` array and not expand into multiple objects and return empty string for the `name` in that case
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions