-
Notifications
You must be signed in to change notification settings - Fork 759
Description
Proposal: Selector Suffixing for Native CSS Nesting
Summary
This proposal introduces a mechanism for generating derived selectors inside nested CSS rules using two new syntaxes:
&(suffix)
(suffix)
These express a suffix attached to the parent selector, enabling native BEM-style patterns without requiring Sass, Less, or PostCSS.
Example
.container {
&(sm) { ... }
(sm) { ... }
}Desired output:
.container-sm { ... }Motivation
Many widely used CSS methodologies depend on suffixing a base selector:
.btn-primary.alert-warning.text-center.container-sm.card-header-title
Preprocessors allow this via:
.btn {
&-primary { ... }
}But &-primary cannot be standardized due to grammar ambiguity.
Native CSS currently has no way to express selector suffixes inside nested structures.
This proposal introduces a clean, unambiguous, and extensible syntax for such cases.
Why &-suffix Cannot Be Standardized
Native CSS cannot parse:
&-primary
because -identifier may be confused with:
- a type selector
- an ident token
- an invalid selector
- part of a compound selector
This prevents suffixing from being exposed in CSS Nesting.
Parentheses resolve the ambiguity.
Proposed Syntax
Option A — Explicit form: &(suffix)
.block {
&(header) { ... }
&(title) { ... }
}Produces:
.block-header { ... }
.block-title { ... }Option B — Minimal form: (suffix)
.block {
(header) { ... }
}Produces:
.block-header { ... }Grammar Proposal
Option A
derived-selector:
& '(' ident-token ')'
Option B
derived-selector:
'(' ident-token ')'
Expansion rule (both options)
<parent-selector> "-" <suffix>
Examples
Simple component modifiers
.btn {
&(primary) { ... }
(outline) { ... }
}Produces:
.btn-primary { ... }
.btn-outline { ... }
Deep BEM-style derivation
.block {
(header) {
(title) { ... }
}
}Produces:
.block-header-title { ... }
Combining with regular nesting
.card {
(header) {
& span { ... }
}
}Produces:
.card-header span { ... }
Real-world utility example
.text {
(start) { text-align: left !important; }
(end) { text-align: right !important; }
(center) { text-align: center !important; }
(decoration) {
(none) { text-decoration: none !important; }
(underline) { text-decoration: underline !important; }
(line-through){ text-decoration: line-through !important; }
}
(lowercase) { text-transform: lowercase !important; }
(uppercase) { text-transform: uppercase !important; }
(capitalize) { text-transform: capitalize !important; }
(wrap) { white-space: normal !important; }
(nowrap) { white-space: nowrap !important; }
(break) {
word-break: break-word !important;
overflow-wrap: break-word !important;
}
(danger) { color: #FF0000; }
(success) { color: #00FF00; }
}Origin of the Idea (Initial Syntax Attempt)
When I first tried to simplify repetitive class families such as .text-*, .placeholder-*, and .container-*, I naturally gravitated toward a syntax already familiar in preprocessors:
.text {
&-center { … }
}This expands to:
.text-center { … }This notation is intuitive, already widely used, and works conceptually as “append a suffix to the current selector.”
However, while testing native CSS nesting, this pattern does not work. The & operator in CSS nesting is explicitly designed for replacing the selector, not extending it as a suffix. Therefore, the syntax looked valid but produced invalid output.
Why the Syntax Evolved into (suffix) and &(suffix)
To avoid ambiguity with both:
- the existing
&replacement operator, and - attribute selectors such as
[data-*]
I explored a more visually compact and explicit form.
This led to the proposed syntax:
.text {
(center) { … } /* becomes .text-center */
&(center) { … } /* explicit suffix for cases that need it */
}Reasons for this evolution:
- Parentheses already exist in CSS grammar (functions, calc(), var(), etc.) and are visually neutral.
- Unlike square brackets ([]), parentheses do not collide with selector semantics.
- (suffix) clearly communicates transformation rather than selection.
- It visually matches the mental model of “attach this to the parent name.”
- It avoids overloading [ ], which already has semantic meaning in selectors.
- For developers familiar with preprocessors, both (suffix) and &(suffix) feel natural.
Visual Comparison
What I intuitively wanted:
.text {
&-center { text-align: center; }
}But native CSS nesting cannot interpret it.
The improved conceptual model:
.text {
(center) { text-align: center; }
}Expands to:
.text-center { text-align: center; }This syntax is:
- concise
- unambiguous
- visually clean
- consistent with how humans already reason about suffix utilities
Backward Compatibility
- No existing CSS pattern uses standalone
(ident)as a selector. - No conflict with pseudo-classes (
:is required). - No conflict with properties or functions.
- Browsers can ignore unknown constructs safely if necessary.
Questions for CSSWG
- Should suffix insertion always use "-" as the joining character?
- Should prefix-style derivation be considered?
- Should both syntaxes —
&(suffix)and(suffix)— be standardized? - Should chaining be allowed?
- Should multiple suffix blocks concatenate?
Optional Extension: BEM and Pseudo-selector Derivation Using Symbol Prefixes
In addition to the main proposal (&(suffix) and (suffix)), an optional extension may allow symbol-prefixed suffixes to support common naming conventions, especially BEM and pseudo-selectors.
Many codebases rely on structural naming such as:
- BEM modifiers:
.block--modifier - BEM elements:
.block__element - Pseudo-class variants:
.block:hover - Pseudo-element variants:
.block::after
Allowing these patterns to be derived natively from nested CSS would significantly increase the expressiveness of native nesting and reduce reliance on preprocessors.
Proposed Optional Syntax
Inside a nested rule:
.block {
(--warning) { ... }
(__title) { ... }
(:hover) { ... }
(::after) { ... }
}Benefits
- Mirrors established BEM naming conventions
- Supports pseudo-class derivation in nesting
- Syntactically unambiguous
- Lightweight extension on top of the primary proposal
Note
This extension is not required for the core suffixing proposal but is included as a potential enhancement for CSSWG consideration.
Conclusion
Native CSS Nesting is an important step forward, but suffix derivation remains a major missing capability currently only possible through preprocessors.