Description
Opening per action item in today’s telcon ( #8738 (comment) )
Problem
We currently desugar every nested rule using :is()
, even when it’s completely redundant. E.g. this:
.foo, #bar {
& {
color: red;
}
}
apparently becomes:
:is(.foo, #bar) {
color: red;
}
This is not only redundant, it actually has observable side effects: since :is()
has a flat specificity equal to the specificity of its argument with the highest specificity, the second rule is not equivalent to the first.
But even worse, because :is()
cannot do pseudo-elements, it means this doesn’t work at all:
.foo::before {
padding: 1em;
@media (width < 500px) {
padding: .5em;
}
}
It would be rewritten like:
.foo::before {
padding: 1em;
}
@media (width < 500px) {
:is(.foo::before) {
padding: .5em;
}
}
which is invalid.
It also means we cannot fix #8738 by wrapping bare declarations after rules in & {}
because in pseudo-elements they could be ignored.
Proposed solution
Edit: I'm not in favor of this any more, see #9492 (comment)
& {}
should have no observable side effects. There is never a case where &
needs :is()
to be rewritten, so adding it not only introduces the problems discussed above, but is entirely redundant.
So a quick fix to the pressing issues could be to simply special case &
.
Later down the line, we may want to consider expanding the set of cases that don’t require :is()
because there is no danger of combinatorial explosion. From a quick call with @fantasai it seems to us that e.g. cases where there are only simple selectors all the way up would not need :is()
, but more research is needed.