DEV Community

Cover image for @supports Lies: When CSS Says 'Yes' but Browsers Say 'LOL No'
Alvaro Montoro
Alvaro Montoro Subscriber

Posted on • Originally published at alvaromontoro.com

@supports Lies: When CSS Says 'Yes' but Browsers Say 'LOL No'

False positives in nested feature detection

According to the CSS Conditional Rules specification, the @supports at‑rule was originally only valid at the top level or inside another conditional group rule. The newer CSS Nesting specification expands this and explicitly allows @supports to appear inside nested style rules as well.

However, even when visually nested, a @supports rule does not inherit the surrounding selector. Browsers still evaluate it as if it were at the top level, which can be confusing:

.my-class {
  @supports (property: value) {
    ...
  }
}
Enter fullscreen mode Exit fullscreen mode

While that @supports rule appears inside a style rule, it is not relative to that selector. It is applied in a general, global way (as if it were written at the root level) even though its placement suggests otherwise. This mismatch between placement and behavior is what makes nested @supports misleading.

Take this example:

li::marker {
  @supports (content: " - ") {
    content: " - ";
    color: red;
  }
}
Enter fullscreen mode Exit fullscreen mode

This works in most browsers. Chrome, Safari, and Firefox support ::marker, and they all support content: " - ". But here's the catch: Safari does not support content inside ::marker.

With the code above, Chrome and Firefox render a red " - ", while Safari renders a red circle instead.

The confusing part is that the @supports condition succeeds even though the declaration is not actually supported in that specific context.

To be fair, this is probably less about browsers "moving" (or more accurately "parsing") nested @supports rules to the top level or in general context, and more about how @supports itself is defined. The feature checks if a declaration is generally valid, not if it is syntactically valid for a specific selector or pseudo-element context.

Maybe one solution would be to extend and (or introduce a new operator or function) so @supports checks can validate combinations rather than independent features. For example:

@supports selector(::marker) and (content: " - ")
Enter fullscreen mode Exit fullscreen mode

or

@supports selector(::marker) xand (content: " - ")
Enter fullscreen mode Exit fullscreen mode

or

@supports rule(::marker { content: " - " })
Enter fullscreen mode Exit fullscreen mode

That would allow to test if a declaration truly works within a given rendering context, instead of only checking if the syntax is recognized.

Another (more ideal) solution would be for browsers to evaluate @supports relative to the scope in which it appears. But that may require too much computation... but hey! they said the same about :has(), and look at it go today!

Note: I know container and style queries may be a workaround, but they only have partial support and can only check for custom properties, not declarations (at least at the moment). Their use could help but wouldn't remove the misleading/limited nature of nested @supports.

Top comments (5)

Collapse
 
alohci profile image
Nicholas Stimpson

I believe the idea that the construct is invalid according to the CSS specifications is incorrect. The CSS-nesting-1, section 3.3. Nesting Other At-Rules says "... this specification allows nested group rules inside of style rules: any at-rule whose body contains style rules can be nested inside of a style rule as well, unless otherwise specified."

It goes on to say in a note:

Specifically, these rules are capable of being nested group rules:

all the conditional group rules (@container, @media, @supports)

@layer

@scope

I do take what you say about that @supports is not computed in context being potentially confusing though.

Collapse
 
alvaromontoro profile image
Alvaro Montoro

Ok. I updated the article to reflect this suggestion I had to tweak many parts, but I think now it should be more accurate and better. Thanks for pointing this out.

Collapse
 
alvaromontoro profile image
Alvaro Montoro

🤦 This is probably me reading the editor's draft instead of working draft, and misunderstanding the placement section a little:

Conditional group rules are allowed wherever style rules are allowed (at the top-level of a style sheet, as well as within other conditional group rules)

I was bamboozled :P

Updating the article....

Some comments may only be visible to logged-in visitors. Sign in to view all comments.