w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.52k stars 673 forks source link

[css-nesting] Treating nesting as syntactic sugar? #8698

Open plinss opened 1 year ago

plinss commented 1 year ago

Disclaimer, I'm not sure I'm actually in favor of this, but I thought I'd throw it out there for discussion.

During the transition period until authors can reliaibly just serve stylesheets containing nesting, authors will either need to transpile their stylesheets into non-nested form, differentially serve nested and non-nested versions, or somehow use a polyfill to convert nested stylesheets into non-nested form for older browsers.

Each of these cases complicates any code that uses the CSSOM to interact with the stylesheet. What if we treated nesting as parse-time syntactic sugar and always generated the CSSOM in the un-nested form?

Loirooriol commented 1 year ago

Then it would be trivial to have a combinatorial explosion. Somewhat like what's described in https://github.com/w3c/csswg-drafts/issues/8310#issuecomment-1383810771.

ByteEater-pl commented 1 year ago

What if we treated nesting as parse-time syntactic sugar and always generated the CSSOM in the un-nested form?

How about both? I.e. have the CSSOM contain the nested and unnested versions.

Then it would be trivial to have a combinatorial explosion. Somewhat like what's described in https://github.com/w3c/csswg-drafts/issues/8310#issuecomment-1383810771.

But the internal representation can still be succint.

plinss commented 1 year ago

Then it would be trivial to have a combinatorial explosion

The author would face the same explosion when transpiling the stylesheet to a non-nested version for older browsers. So not likely to be an issue in the real world.

Loirooriol commented 1 year ago

Apparently SASS uses some heuristics to avoid several expansions, mitigating the combinatorial explosion. So unless we adopt something like that, it will be worse.

tabatkins commented 1 year ago

In general, having the OM not reflect the stylesheet is something we should avoid as much as possible; we don't need to perfectly reproduce the source and so can do some normalization, but shouldn't dramatically rewrite things. I think doing this would definitely violate that.

(Sass actually doesn't prevent this particular exponential explosion; the heuristics I've been thinking about this whole time are about @extend expansion.) But it's still the case that having the blow-up happen at build time, where it can be more obvious and results in gigantic transfers that are hopefully easily noticeable (and which is reliably easier for the user to interrupt), is different than the blowup happening on the client-side, internally in the browser. We try to avoid Billion Laughs attacks.

plinss commented 1 year ago

In general, having the OM not reflect the stylesheet is something we should avoid as much as possible;

I agree (and as I said above I'm not sure I'm actually in favor of this proposal). Normally, I'm already bothered by the amount of normalization we do in serialization.

Where this came from was the thought experiment of a site serving a nested stylesheet but having a polyfill to desugar it for older clients (or differentially serving the desugared version as needed). In that case, any code that interacts with the stylesheet needs to be prepared to work with either version of the OM, which can get awkward. If the client just always desugared, they'd both have the same OM. Provided the polyfill and/or transpiler did the desugaring correctly, and we'd need to specify that, but we sort of do that anyway by explaining how the nested rules behave.

If we did this tho, we'd consider the desuarging part of the normalization (yeah, it's a stretch). An other aspect of that would be possibly converting existing rules into nested ones during serialization. Again, a stretch, and not something I think I'm in favor of, but it's sort of consistent...

A possible alternative would be adding a method that converts a nested stylesheet to a desugared one (and possibly one to nest everything that can be). That way if an author can get either version of a stylesheet, and wants to only write one set of code to deal with it, they can convert back and forth at runtime... That might make more sense as a library in userland tho.

SebastianZ commented 1 year ago

A possible alternative would be adding a method that converts a nested stylesheet to a desugared one (and possibly one to nest everything that can be). That way if an author can get either version of a stylesheet, and wants to only write one set of code to deal with it, they can convert back and forth at runtime...

+1 on that. This provides authors with a simple option to provide a polyfill for older browsers.

That might make more sense as a library in userland tho.

I'd argue that that would be way harder to do and a lot less performant than a built-in API.

Sebastian

SebastianZ commented 1 year ago

That might make more sense as a library in userland tho.

I'd argue that that would be way harder to do and a lot less performant than a built-in API.

Sebastian

Faulty reasoning. 🤦🏻 That API would, of course, not be available in older browsers. 😄 So yeah, that'd need to be a complete polyfill.

Sebastian

tabatkins commented 1 year ago

The important question to ask is, are you actually gonna need it? It's fundamentally a sugar operation, and while all of Nesting is sugar, we must keep in mind what the audience size is of the sugar, and how much benefit it brings them.

I suspect that the audience for "I'm serving identical stylesheets for old and new browsers, except one uses Nesting and the other doesn't, and I need to normalize both of them to a common format because I'm doing some CSSOM manipulation of the stylesheet itself" is a pretty small segment of the author population. ^_^ So, "do it in a library" is probably the better solution for this.