- From: Miguel92 via GitHub <noreply@w3.org>
- Date: Wed, 10 Dec 2025 22:08:41 +0000
- To: public-css-archive@w3.org
joelmiguelvalente has just created a new issue for https://github.com/w3c/csswg-drafts:
== [Proposal] Selector Suffixing for Native CSS Nesting ==
# 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
```css
.container {
&(sm) { ... }
(sm) { ... }
}
```
Desired output:
```css
.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:
```scss
.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)`
```css
.block {
&(header) { ... }
&(title) { ... }
}
```
Produces:
```css
.block-header { ... }
.block-title { ... }
```
## Option B — Minimal form: `(suffix)`
```css
.block {
(header) { ... }
}
```
Produces:
```css
.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
```css
.btn {
&(primary) { ... }
(outline) { ... }
}
```
Produces:
```
.btn-primary { ... }
.btn-outline { ... }
```
## Deep BEM-style derivation
```css
.block {
(header) {
(title) { ... }
}
}
```
Produces:
```
.block-header-title { ... }
```
## Combining with regular nesting
```css
.card {
(header) {
& span { ... }
}
}
```
Produces:
```
.card-header span { ... }
```
## Real-world utility example
```css
.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:
```css
.text {
&-center { … }
}
```
**This expands to:**
```css
.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:**
```css
.text {
(center) { … } /* becomes .text-center */
&(center) { … } /* explicit suffix for cases that need it */
}
```
**Reasons for this evolution:**
1. Parentheses already exist in CSS grammar (functions, calc(), var(), etc.) and are visually neutral.
2. Unlike square brackets ([]), parentheses do not collide with selector semantics.
3. (suffix) clearly communicates transformation rather than selection.
4. It visually matches the mental model of “attach this to the parent name.”
5. It avoids overloading [ ], which already has semantic meaning in selectors.
6. For developers familiar with preprocessors, both (suffix) and &(suffix) feel natural.
## Visual Comparison
**What I intuitively wanted:**
```css
.text {
&-center { text-align: center; }
}
```
But native CSS nesting cannot interpret it.
**The improved conceptual model:**
```css
.text {
(center) { text-align: center; }
}
```
**Expands to:**
```css
.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
1. Should suffix insertion always use "-" as the joining character?
2. Should prefix-style derivation be considered?
3. Should both syntaxes — `&(suffix)` and `(suffix)` — be standardized?
4. Should chaining be allowed?
5. 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:
```css
.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.
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/13205 using your GitHub account
--
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Wednesday, 10 December 2025 22:08:42 UTC