Repository navigation
[css-properties-values] CSSOM for multi-name and shorthand @property #14227
Description
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
- Existing single-name
@propertyrules MUST produce the same CSSOM - Any syntax that only fans out on
nameonly (e.g.CSSPropertyRule.prototype.names) will have trouble once the shorthandsyntaxsyntax is introduced ([css-properties-values-api] Shorthand for custom property declaration #7523)
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.nameis 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
namewritable later would be hard insertRule()can insert multiple rules, which is weird
Option 2: name/names
This includes:
nameincludes the full comma-separated list, no other changenameincludes the full comma-separated list,namesas aFrozenArraynameis empty when multiple names,namesas aFrozenArray
Pros:
- Serialization roundtrips
Cons:
- All of these special case the name fanout, unclear how this expands to the
syntaxshorthand. In theory we could add plural versions of all descriptors as shorthands are added (syntaxesetc), 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 generatecssRules.
Cons:
- Biggest lift, incompatible with code consuming the existing schema
- Requires additional design decisions for every single descriptor on the root object
- What would
namebe? Empty? A comma-separated list? The first name? - What would
syntaxbe once we have the shorthand syntax? Empty? A union of all? The first one? - etc
- What would
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.
Metadata
Metadata
Assignees
Type
Projects
- StatusShow more project fieldsThursday Afternoon
Activity
emilio commentedon Jul 25, 2026
There are other options, like 2 but multiple names return empty for
name. That's somewhat similar to what we did for@containerwhen 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.
LeaVerou commentedon Jul 26, 2026
I added this to the post. Is this an example or do you have more options in mind?
That works for
@containerbecause 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…).It was specific to the option where
nameholds the whole thing. Clarified in the OP.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.
[-][css-properties-values] CSSOM for multi-name `@property`[/-]Loirooriol commentedon Jul 26, 2026
What do you mean with the syntax shorthand?
LeaVerou commentedon Jul 26, 2026
The
@property --name <syntax>: initial-value, --name2 <syntax2>: initial-value2, ...shorthand discussed in #7523Loirooriol commentedon Jul 26, 2026
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.
css-meeting-bot commentedon Aug 6, 2026
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 caseThe 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
Update registration tests for descriptor defaults