- From: Paceaux via GitHub <noreply@w3.org>
- Date: Tue, 14 Jul 2026 17:32:31 +0000
- To: public-css-archive@w3.org
paceaux has just created a new issue for https://github.com/w3c/csswg-drafts:
== [css-selectors-5] @selector function for creating custom selectors ==
I would like to suggest that there exist a feature within selectors that offers some sort of parity to what already exists within CSS values: the ability to create and interpolate a string value.
## Problem: Specificity bloat leads to file bloat
Suppose a very real in-production selector:
```
#foo-navigation[breakpoint=desktop] .hidden-at-desktop[class][class][class],
foo-navigation[breakpoint=desktop] .hidden-at-desktop[class][class][class] {
display:none
}
```
This is one of a series of rulesets that are unfortunately high due to specificity bloat that lives outside the domain of the stylesheet.
But a side-effect of raising the specificity to accomplish the goal is that the selectors must requisitely become longer (lest we resort to !important or `id` selectors).
### Solution 1: Nesting (already exists)
Nesting could be one solution to reducing redundancy, but it comes at the cost of incidental specificity sideeffects, since the most -specific selector in the list would elevate the specificity of all selectors (due to the fact that nesting uses the same mechanics as `:is()` under the hood)
So someone could write
```css
#foo-navigation[breakpoint=desktop], foo-navigation[breakpoint=desktop]) {
.hidden-at-desktop[class][class][class] {
}
}
```
which is functionally equivalent to `:is(#foo-navigation[breakpoint=desktop], foo-navigation[breakpoint=desktop]) .hidden-at-desktop[class][class][class] `.
But now `foo-navigation` is given the specificity of an id, which could have un intended consequences. Not only that, the duplication is eliminated with the child elements; so the code doesn't immediately express what problem is solved with nesting.
### Solution 2: `:where()`
It might be tempting to instead eliminate redundancy by using `:where()` since neither it nor its arguments contribute specificity:
```css
:where(#foo-navigation[breakpoint=desktop], foo-navigation[breakpoint=desktop]) .hidden-at-desktop[class][class][class] {
display: none;
}
```
Unfortunately this creates the exact problem that now all specificity is _gone_, and this may also not be a desired outcome.
### Solution 3: CSS Selector Function (proposed)
One solution could eliminate redundancy, improve cognitive load, and not create specificity side-effects:
```css
@selector --<name>() {
<valid selector string>
}
```
A real-world use-case could be as follows:
```css
@selector --foo-nav-desk() {
#foo-navigation[breakpoint=desktop]
}
:--foo-nav-desk() .hidden-at-desktop[class][class][class] {
}
```
In this case, the custom selector function has been set to not provide _any_ specificity. It will behave like a CSS custom property and handle the returned argument like a string and the value will be rendered at request time.
This solution would also mimic the behavior of the CSS function syntax.
### Problem: Interpolating CSS selectors
Currently, it is not possible to interpolate CSS selectors.
In other words, this selector cannot be made less redundant or reusable with any selector-generating syntax
```CSS
#foo-navigation[breakpoint=desktop] .hidden-at-desktop[class][class][class],
foo-navigation[breakpoint=desktop] .hidden-at-desktop[class][class][class] {
display:none
}
```
*Solution: Allow string arguments passed into a selector function*
I would propose this syntax:
```css
@selector --<name>(<variable>) {
<interpolated string>
}
```
essentially, the arguments, however many, would be inserted as-is whereever the `var` keyword is used (just like with properties).
In this case, an application could be like so:
```CSS
@selector --foo-nav(--desktop) {
#foo-navigation[breakpoint=var(--desktop)]
}
:--foo-nav(desktop) .hidden-at-desktop[class][class][class] {
display: none;
}
:--foo-nav(mobile) .hidden-at-desktop[class][class][class] {
display: none;
}
```
## TL;DR
Proposing a selector function would allow us to reduce duplicativity as developers without specificity side-effects. smaller stylesheets without side-effects makes for happier end-users.
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/14180 using your GitHub account
--
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Tuesday, 14 July 2026 17:32:31 UTC