csswg-drafts icon indicating copy to clipboard operation
csswg-drafts copied to clipboard

[css-nesting-1] Why is CSSNestingRule separate?

Open sesse opened this issue 3 years ago • 3 comments

The CSSOM part of css-nesting-1 extends CSSRule to support children:

https://csswg.sesse.net/css-nesting-1/#cssom-style

However, then it goes ahead and defines a separate interface, entirely unrelated to CSSRule, for nest:

https://csswg.sesse.net/css-nesting-1/#cssom-nesting

I don't understand why these need to be separate. From what I can see, they are identical except for the name. (Also, CSSRuleList does not support containing CSSNestingRule? Wouldn't it need to?) Could we maybe unify them? A proposal would be something like:

  • CSSRule is modified as per the current spec.
  • CSSNestingRule is removed.
  • Direct-nested rules are to be treated as a convenient shorthand for @nest rules.
  • When serializing a rule with a nest-containing selector, “@nest ” is added at the start iff not all selectors are nest-prefixed.

In the same vein, there is something that appears to be slightly underspecified: The algorithm for CSSNestingRule's selectorText setter only specifies “if the algorithm returns a non-null value”, but it doesn't explicitly write anywhere that all selectors need to be nest-containing. This makes it potentially possible to write a non-nest-containing nested rule using CSSOM.

@emilio

sesse avatar Oct 05 '22 12:10 sesse

They're separate just because all the at-rules have a dedicated type, and it seemed odd for @nest to be the one exception.

Dropping it and just using CSSStyleRule is definitely possible, however. The big issue is just that you wouldn't preserve whether a style rule was written with @nest or not (unless we add some additional state to CSSStyleRule), so a rule like @nest & > .foo {...} would probably serialize down to just & > .foo {...}. (I think that's fine, fwiw.)

(Also, CSSRuleList does not support containing CSSNestingRule? Wouldn't it need to?)

What do you mean by that? It's a list of CSSRule objects with no further checking performed, and CSSNestingRule is a CSSRule subclass.

In the same vein, there is something that appears to be slightly underspecified: The algorithm for CSSNestingRule's selectorText setter only specifies “if the algorithm returns a non-null value”, but it doesn't explicitly write anywhere that all selectors need to be nest-containing. This makes it potentially possible to write a non-nest-containing nested rule using CSSOM.

Yup, that's a bug.

tabatkins avatar Oct 05 '22 20:10 tabatkins

Dropping it and just using CSSStyleRule is definitely possible, however. The big issue is just that you wouldn't preserve whether a style rule was written with https://github.com/nest or not (unless we add some additional state to CSSStyleRule), so a rule like @nest & > .foo {...} would probably serialize down to just & > .foo {...}. (I think that's fine, fwiw.)

Yes, I would say so, too. Especially with the syntax now seemingly going in the direction of supporting many more explicit things. It seems odd to me to have a special rule type whose only difference is that it serializes with @nest in front; if so, I'd prefer simply having a flag somewhere? But just serializing to the shortest possible form seems better to me.

sesse avatar Oct 07 '22 13:10 sesse

Another thing I guess we'd need to care about: If I have a rule

.foo {
  & .bar { … }
}

and then do document.styleSheets[0].rules[0].rules[1].selectorText = '.bar &';, does it suddenly change type to CSSNestingRule, or is this illegal?

sesse avatar Oct 18 '22 09:10 sesse

Closing, as the OP's issue was addressed (we dropped the CSSNestingRule interface and just reuse CSSStyleRule now).

The issue about mutating the selector of an existing rule to no longer be valid is tracked in #7971.

tabatkins avatar Jan 10 '23 23:01 tabatkins