(Note: Edited on Jul 24th, 2026 to focus on wildcard prefixes. Comma-separated syntax shortcut moved to #14225 )
The problem
It's common to register a number of properties that share the same prefix with the same descriptors.
When the properties are known in advance, and are relatively few, #14225 covers it.
However, when the set is mutable, large, and/or not known in advance, this gets really messy.
Examples
Proposal
Support an optional single wildcard at the end of <custom-property-name>.
It would be mandatory to precede the wildcard by -, both to reduce the size of any Bloom filters used by implementations but also for author-facing reasons, to prevent uninentional matches.
With #14225 the 4000 lines of property registrations here remain 4000 lines, just lighter.
With this, they collapse to 1:
@property --i-* {
syntax: "<number>";
initial-value: 0;
inherits: true;
}
Spec changes
https://drafts.css-houdini.org/css-properties-values-api/#at-property-rule
The production corresponds to this: it’s defined as any (a valid identifier that starts with two dashes), except -- itself, which is reserved for future use by CSS. Custom properties are solely for use by authors and users; CSS will never give them a meaning beyond what is presented here.
to:
The production is defined as:
<custom-property-name> = <dashed-ident> [ '-*']?
with the exception that it excludes -- itself, which is reserved for future use by CSS. Custom properties are solely for use by authors and users; CSS will never give them a meaning beyond what is presented here.
Alternatively, since <dashed-ident> does not permit *, I suppose we'd need to define a new token, e.g. <dashed-ident-glob> or <dashed-ident-pattern> or <dashed-ident-set>.
CSSOM changes
We could introduce conveniences later, but no CSSOM changes are needed for an MVP:
CSS.registerProperty() could just accept these tokens under name
- CSSOM can represent these under a single
CSSPropertyRule.
Challenges
Conflict resolution
In the same spirit as #14225, @property rules do not cascade. If multiple match, only one wins.
However, I think there is value in tweaking the "last one wins" rule:
- Exact wins over wildcard, regardless of order
- Between two prefix rules, the longest one wins, regardless of order
- Otherwise, last one wins
This means this works as expected:
@property --icon-* {
syntax: "<image>";
inherits: true;
}
@property --icon-start, --icon-end {
syntax: "<image>";
inherits: false;
}
or this:
@property --size-* {
syntax: "<length>";
inherits: true;
}
@property --size-rel-* {
syntax: "<length-percentage>";
inherits: true;
}
Other related issues
(Note: Edited on Jul 24th, 2026 to focus on wildcard prefixes. Comma-separated syntax shortcut moved to #14225 )
The problem
It's common to register a number of properties that share the same prefix with the same descriptors.
When the properties are known in advance, and are relatively few, #14225 covers it.
However, when the set is mutable, large, and/or not known in advance, this gets really messy.
Examples
--int-*,--length-*etc see tweet by @propjockey.@tabatkins said they think it is feasible.
Proposal
Support an optional single wildcard at the end of
<custom-property-name>.It would be mandatory to precede the wildcard by
-, both to reduce the size of any Bloom filters used by implementations but also for author-facing reasons, to prevent uninentional matches.With #14225 the 4000 lines of property registrations here remain 4000 lines, just lighter.
With this, they collapse to 1:
Spec changes
https://drafts.css-houdini.org/css-properties-values-api/#at-property-rule
to:
Alternatively, since
<dashed-ident>does not permit*, I suppose we'd need to define a new token, e.g.<dashed-ident-glob>or<dashed-ident-pattern>or<dashed-ident-set>.CSSOM changes
We could introduce conveniences later, but no CSSOM changes are needed for an MVP:
CSS.registerProperty()could just accept these tokens undernameCSSPropertyRule.Challenges
Conflict resolution
In the same spirit as #14225,
@propertyrules do not cascade. If multiple match, only one wins.However, I think there is value in tweaking the "last one wins" rule:
This means this works as expected:
or this:
Other related issues