WebKit Supports Nested CSS
webkit.org
webkit.org
> Web developers responded to the poll with great clarity. Option 3 won in a landslide.
Yup, pretty much. The only thing I really wish won however was making the beginning "&" always required for nesting. Instead you're able to omit it if there's any other symbol. Example from article:
main {
.bar { ... }
#baz { ...}
:has(p) { ... }
::backdrop { ... }
[lang|="zh"] { ... }
\* { ... }
+ article { ... }
> p { ... }
~ main { ... }
}
The position of requiring & was not represented in the poll but seemed really popular in all the comments and seems like it would only make the parser's job easier (both now and in the future of CSS)Regardless I'm just happy it's finally here! Hard to see the use-cases for sass in 2024 but, like jQuery, it's definitely made its mark on the history of the development of web standards
Personally I do agree and I like the explicitness of always having the &
https://twitter.com/LeaVerou/status/1580215877705687040, a poll about this specific matter (with links to other relevant polls which on the surface contradict this one).
https://github.com/w3c/csswg-drafts/issues/7834#issuecomment..., on this exact matter (chosen as a convenient starting point, after matters were already settled, but the whole issue is about it). By the time this poll was done, they had already decided not to consider mandatory-&, though I don’t really understand why (it’s pretty obvious to me that dividing into 3a and 3b would have been much more interesting than a couple of the other options which were straw men that no one was capable of taking seriously even if they tried).
https://github.com/w3c/csswg-drafts/issues/7961, about doing away with & in all cases for descendant selector (… which would be terrible for complexity and worst-case performance, and is only being considered because they already made things inconsistent by making & optional in every other case).
(I don’t like where it’s ended up, and consider requiring the & in all cases to be obviously materially superior, for both machine and human handling, and that there’s clear concrete advantage in having the requirement as an actual language rule rather than only a linter-enforced choice. People are far too hung up on exactly Sass syntax.)
> it would only make the parser's job easier
Mind you, it’s not a big difference; it’s just “if there’s no & in the selector, insert one and a descendant combinator at the start” in some shape, which could be as little as half a dozen lines of code net.
- Easier for human readers (the "&" is an unmistakable visual indicator)
- Easier for human writers (fewer decisions; there's Only One Way To Do It)
- Easier for syntax colouring
Perhaps controversial, I know. I realize this eliminates use cases like
em {
color: green;
li & {
color: red;
}
}
It's okay not to support these use cases. They're confusing because they break encapsulation; the rule that appears to be nested inside (in this case, color: red) is affected by an element on the outside (in this case, <li>).Compare:
li {
color: blue;
}
em {
color: green;
li & {
color: red;
}
}
To: em {
color: green;
}
li {
color: blue;
& em {
color: red;
}
}
The second structure is easier to understand, and in my opinion, the syntax should bias you toward writing it that way.On your example: nesting is not about the sort of encapsulation you think it is—that’s incidental at best. It’s perfectly reasonable to say “this chunk of styles is about <em> elements; and when they’re inside <li>, do this”. The specific example you’ve given is also unrealistic with all three rules touching the same property in this way and two mutually exclusive (that is, li and em cannot both match, in any DOM), and I wouldn’t want it written with nesting at all, but rather like this, for much-increased clarity:
li {
color: blue;
}
em {
color: green;
}
li em {
color: red;
}Possibly mixins, loops, and variables, which, unlike CSS variables, can be used in media queries.
Please god no. CSS is intended to be completely declarative. Loops and conditional logic were the very worst ideas SASS ever had.
Then in-between then and now, I did a lot of consulting work, and now I'm strongly feeling that the more DRY you try to make CSS, the more you end up writing, and unmaintainable CSS at that. Random example:
https://github.com/primefaces/primeflex/blob/master/_sass/li...
SASS is too powerful for its own good.
TL;DR: I wholeheartedly agree with the above comment.
css variables in media queries would be helpful too, but mixins to me is the next big step after :has() (oh so useful, come on firefox!) and this nested css syntax. unfortunately, it may be years for us to see it in browsers. there's no consensus yet on mixin syntax or where in the css lifecycle it would be implemented (there are potentially serious performance implications apparently).
Modules make writing CSS much less of a naming game. Anything you can do to reduce one of the 2 hardest problems in CS is worth it.
Because there was no “none of the above” option, which developers asked for.
Here's one:
.foo .bar {
.baz & {
color: red;
}
}
In Sass, that would compile to: .baz .foo .bar {
color: red;
}
With native nesting, it effectively compiles to: .baz :is(.foo .bar) {
color: red;
}
The Sass version matches this DOM structure: <div class="baz">
<div class="foo">
<div class="bar">
...
But the native version matches all of these structures: <div class="baz">
<div class="foo">
<div class="bar">
...
<div class="foo">
<div class="baz">
<div class="bar">
...
<div class="foo baz">
<div class="bar">
...
Not a criticism at all (the `:is(...)` behavior is a very useful and welcome enhancement to CSS) but a notable difference worth understanding coming from Sass.(We discussed adopting Sass's behavior in <https://github.com/w3c/csswg-drafts/issues/8310#issuecomment...> but ultimately dropped it.)
I recognize this is a preview and I desperately hope this implementation isn’t kept around and treated as a quirk.
This implementation is extremely unintuitive given their explanation of the expected behavior of CSS Nesting and the & symbol.
To quote:
The & signals to the browser “this is where I want the selector from outside this nest to go”.
Their explanation and the actual implementation result in a majorly different CSS selector.The implemented functionality, however useful, makes no sense as a default if one can explicitly use :is to achieve this behavior like below.
.foo .bar {
.baz :is(&) {
}
}
The default should behave like they claim it does; simply replace & with the “outside” selector.In Sciter, 10 years ago, I came up with style sets:
@set Main {
:root { ... } // root element that has this set applied
.bar { ... }
article { ... }
:root > article { ... }
}
main { style-set: Main; } // main element with the set applied
This solution solves two problems:1. Modular/componentized style definition - same goal as in nesting styles, but without introduction of new syntax constructs.
2. Reduces CSS resolution load. Rules inside the set are scanned only for DOM children that have style set defined.
3. DOM element may have @styleset="url#name" attribute defined - used in components (Web alike components and React alike components)
Syntactic sugar, sometimes, is the promise of sunnier mornings and that matters.
Anyway programmers given nesting just do it all the time which ends up leading to stuff like
article.news section.preamble h1 and probably a few other selectors after that all nested giving you a wonderful high priority for your style and possible collisions.
Then the same guys who made the problem can't figure out the problem so they figure some highlevel nesting is the solution so there won't be any collisions and overriding of styles.
If users stick to nesting for lightweight scoping, things will go well. But they wont: they’ll use it to DRY every possible line and their inheritors will suffer dehydration.
but it is also a source of bugs, because complicated selectors mess with css priority and the cascade then someone writes something that has side effects and blame CSS instead of their ridiculously long nesting.
But not having nesting at all is similarly problematic as having too much nesting, because it can lead to repetition, proliferation of classes and brittleness.
I worked in several codebase that used SCSS and due to those little hacks popping up in review, every time we ended up putting a "rule" in place to stick to two levels of nesting at most, or 3 if you're using the third nesting-level for pseudo-selectors (:hover :before etc). And this rule very rarely had to be broken, as it was extremely easy to avoid being too clever with nesting. (Of course, if there was a real good technical reason, we'd "break" it too).
When you want to add a feature you should ask first if that can be accomplished by existing mechanisms.
And the second, if to go with with the change that affect millions of users, can we solve not just one problem (that already has a solution like LeSS & Co.) but possibly other principal too?
So for #1. If we already have @media sections, why not to use the same notation?
@media name { ...rules... }
and @set name { ...rules... }
@set can use existing code in parsers. Not just in browsers but in tons of existing tools and editors that do syntax highlighting.And #2. Style sets solve problem of global CSS namespace pollution.
Consider this rule:
div [name="some"] { ... }
then, while calculating styles of DOM elements, absolutely all N DOM elements need to be checked against this rule. So it is a O(N) complex task. And proposed nested rules thing does not reduce the N, but may make this even worse - more rules will be used.While in style set solution:
@set ComponentA {
div [name="some"] { ... }
}
that rule will be checked only against children of componentA - the rule is local/scoped to DOM subtree. Still O(n), but n <<< N.As for @media queries, I can't say anything about Gecko or WebKit, but at least in Blink they're handled entirely different. And @scope (which is the closest I know of to your hypothetical @set) is significantly less efficient than bucketing is, or even a simple parent selector, since it needs to walk up the DOM after the rule matched.
"All of that is very different between the various engines, making the whole process even less predictable."
Source: https://benfrain.com/css-performance-revisited-selectors-blo...
In worst case complexity of styles resolution is O(nS*nD) where nS is a number of style rules and nD is a number of DOM elements. That's for current flat style table used by CSS. You can optimize bits and cases but it in general problem is like that.
> @media queries ... at least in Blink they're handled entirely different.
@media and @set are different mechanisms. :root in @set matches element that has this set applied. @set's are scoped set of rules. @media are not.
But I was talking about different thing - parsing, in particular in syntax highlighters and other tools.
----
Consider this DOM:
<body>
<aside styleset="styles.css#aside-set">...</aside>
<main styleset="styles.css#main-set">...</main>
</body>
And CSS: @set aside-set {
:root {...}
... nA more rules
}
@set main-set {
:root {...}
... nM more rules
}
<aside> content style resolution will always be constant and independent from <main>, no matter how many nM rules you will have. While currently (with the flat table) adding rules for <main> content will increase complexity of <aside> DOM resolution too.As a bonus: rules in two sets are completely isolated. Adding rule in main-set will never break existing aside design.
Worst-case isn't really interesting for browsers, though. CSS doesn't have an adversarial performance model.
> @media and @set are different mechanisms. :root in @set matches element that has this set applied. @set's are scoped set of rules. @media are not.
Again, this roughly matches @scope (where :scope matches the element that has the given selector applied). But this is just a fantasy spec, right? There are no browsers that implement this, and just like with @scope or nesting or CSS at all, there's no guarantee in the spec what performance characteristics you would have?
FWIW, if you want something like this and get it through CSSWG, you'll most likely see it end up with worse performance than flat CSS, unless it becomes _really_ popular and browsers see the need to optimize certain sub-cases of it (the general case, with tons of different sets, will be nearly impossible to make really fast).
But this syntax can also be used in minified CSS. I'm sure minifiers will have a fun time with this in 5 years when most of the major browsers support it.
I've seen all sorts of examples of stylesheets that would benefit from this, Tailwind Typography being a good one because it styles all sorts of nested elements but only inside of `.prose`. Eliminating tens or hundreds of `.prose` selectors by wrapping them all in a single `.prose { }` would make it smaller; not sure exactly how much smaller though.
This sounds like a fun case study.
Like when writing HTML or regular code, I find indentation helps me parse and navigate the structure very easily.
There are cases with complex components where it can become a bit complex, but it's trivial to split the tree in multiple parts to reduce the indentation.
This is a sign you need to decompose whatever design you are working on into smaller components. If you’re trying to write styles for a whole page at once, you’ll see this problem, but if you are working on small components, it’s very rare.
I haven't followed modern CSS development much. Does it have a module system now?
The problem is that web-components need JS enabled, which really, really sucks. Why should a component that can perfectly render itself using plain HTML and CSS need to have associated JS declaring: "Hey! I am a web-component!". Declarative web components would have made adoption of web-components super-high , but alas, corporate interests are against this feature.
When any complexity becomes too much it makes it harder to reason about. The solution is to avoid complexity; you can do that while using a small number of nested selectors.
https://stylelint.io/user-guide/rules/max-nesting-depth/
I mean, these days almost every JS developer use some kind of linter - why would you not use a linter for CSS? Literally nothing to lose since you can set the rules as relaxed as you want.
PS: I set it to 3 - Using good convention like SuitCSS I have never found I needed more nesting. Usually you think about a problem and find a simpler way to do it.
https://github.com/suitcss/suit/blob/master/doc/naming-conve...
TLDR If you use any of the good practices for CSS such as BEM or BEM-like you don't have lots of nesting anyway.
And I like how the article mentions as an example `ul article ul` and how to solve it by adding a symbol :is() to be able to nest, and it's literally the one thing you don't want to do anyway, which is a selector like `ul article ul` (as per BEM methodology). Instead `.list .article .article-list` as a veyr poor example doesn´t need the special "fix" the article mentions.
Working with SCSS codebases and junior developers, I've seen SCSS nesting get so bad, the line order of the selector in the stylesheet would determine what styling gets used.
Nesting CSS is useful in some cases, but for the majority of use cases it can get unwieldy very quickly.
Nesting is great to avoid selector repetition.
Custom properties (CSS variables) and CSS functions give us tools to avoid magic numbers and to encode layout relationships.
New sets of selectors and container queries let us decouple and re-use declarations more.
CSS Houdini gives us further power in extending CSS functionality.
Of course there are things that SCSS provides which are unlikely in the scope of future CSS proposals such as datastructures (maps) and loops to generate classes and mixins. But I can already imagine a world were those aren't necessary anymore for many cases.
Reminds me of how Coffeescript died out because its best ideas got integrated into Javascript.
What I want to know is: how the hell did this take so long? Nesting is such an obviously useful feature to have in CSS, and once I'd experienced it in SASS I never wanted to be without it. Why did it take 10+ years for this to be introduced to CSS, especially when other browser-based technologies like JS have evolved enormously in that time?
As far as the speed of which things get implemented, I often feel there is a lack of understanding where design and development overlaps. Most devs are just devs in the sense they solve algorithmic/browser rendering problems, and don't really dabble enough with markup/styling languages like HTML and CSS to hit the pain points of using them. And the people that deal with markup/styling do not know the proper channels to rally behind some of the ideas that would make their lives easier. Unfortunately, there are less individuals that are proficient at markup, styling, and programming (not just in the sense of coding in JS/TS, but understanding the internals of the browser and programming for it), and the unicorns that do understand are often snatched up by Google/Microsoft/etc. which often have their own agendas. I feel there's just a lot more niche backdrop knowledge that is required to get the ball rolling. These are just my feelings on this matter, I could be wrong.
This wins in my opinion because there shouldn’t be any conversion necessary from something like Sass to CSS
I Vaguely recall something similar happening with decorator syntax/how it worked in JS/typescript.
Or do you keep to CSS features that are locked down in terms of spec, just waiting on implementation to roll out?
The safe option is obviously to install plugins for features that are close to passing as possible, where the api is stable at least - but there are plugins for very early stage proposals too.
The way TC39 handles stages now should stop things like that from happening. (You implement a Stage 1 or 2 feature fully knowing it could change)
I feel the only big thing missing from the vanilla stack for me right now is a template element that multiple html files can share. Just like how you make a blog header in Jekyll or Hugo and it adds it on all your blog posts get the header. I haven't found an easy way of doing that if I have a bunch of html pages.
They're tracking work in https://bugzilla.mozilla.org/show_bug.cgi?id=1648037
.some-class {
background: blue;
&:hover {background: red}
border: 1px solid;
&:active {border: 1px dashed}
padding: 16px;
display: flex;
gap: 8px;
& > * {
color: red;
}
}
And it would be a pity if that wasn't allowed.The reason I ask is because I seem to remember an early proposal not allowing this, but I can't find where I read it.
> When a style rule contains both declarations and nested style rules or nested conditional group rules, the declarations must come first, followed by the nested rules. Declarations occuring[sic] after a nested rule are invalid and ignored.
[1] https://www.w3.org/TR/2021/WD-css-nesting-1-20210831/#mixing
Fortunately, this has been changed in the most recent proposal[2]:
> When a style rule contains both declarations and nested style rules or nested conditional group rules, all three can be arbitrarily mixed. However, the relative order of declarations vs other rules is not preserved in any way.
Really curious about the reasoning behind that initial quirk
We removed the restriction, but still warn against it due to readability issues.
I think I like it. In general I like the adoption of good features like this. But. It's getting awfully hard to keep track of CSS vs SASS syntax. Starting a greenfield project today I'd leave SASS out of it... but I'm usually working on projects where SASS is already present. Shrug.
(I'd also like more/better color functions out of vanilla CSS. But that's not necessarily a dealbreaker for me in most cases.)
So it's the latest chrome, Safari technical preview, and edge behind a flag. No disposition from Firefox yet afaict.
I've written plenty of parsers (recursive descent, packrat, Pratt, and using generators) and not a single one would have any trouble parsing something like:
html {
body:has(p) {
width: 1000px;
}
}
The only thing I can think of is that they are trying to avoid a lookahead, i.e. you have selectors like "body:has(p) {" which initially look like they could be setting a "body" attribute to the value "has" until you reach the "(". But these lookaheads aren't hard to implement in practice. There are performance issues if the lookahead has to go too deep, but CSS developers can use the & in those cases as an optimization, and you could limit lookahead depth to something like 256 (which would handle the vast majority of non-malicious use cases).Perhaps the lookahead has a lot more drastic effect than I'm expecting on performance for short lookaheads, but I'd like to at least see some profiling of that, as it seems to me like this possibility was discarded without much consideration or explanation (it wasn't even included in the poll).
There's also another way to do this without lookaheads at all, by building up a structure for each potential path and then discarding the one that doesn't complete (I think this is basically a DFA but it's been a while since I read literature on this so I'm forgetting the terminology). This would probably avoid the performance issues but also probably be a larger departure from the current implementation of the parsers.
However, the current spec has been written in a way that it doesn't prevent removing this restriction in the future. But the CSSWG would prefer to have some real world profiling data to know the actual performance cost of removing this restriction.
Is there any conflict with anything that exists in the standard right now?
CSS was designed to be "forgiving" of malformed input, so there's generally no "early" bailout the parser can make, even if it doesn't think it knows which property you are talking about and has a whitelist of specific properties it supports.
Then again, I'm lucky enough to often work with my own 'hand-crafted', semantic html, and not some div soup generated by a tool.
.page form
border: 2px solid #223;
border-radius: 0.15rem;
& button {
background-color: red;
transition: background-color 0.15s ease;
}
&:hover button {
background-color: blue;
}
}
seems way cleaner, easier to read, and more maintainable than the alternative which I don't even wanna type outI really like the look of nested selectors for this reason - because I can group my selectors by component.
.page form {
border: 2px solid #223;
border-radius: 0.15rem;
}
.page form button {
background-color: red;
transition: background-color 0.15s ease;
}
.page form:hover button {
background-color: blue;
}Imagine those three rules in a 200 line CSS file.
E: or would you have to use `>` somehow?
Help choose the syntax for CSS Nesting - https://news.ycombinator.com/item?id=34006622 - Dec 2022 (159 comments)
Updated CSS Nesting Syntax to Avoid Common Copy-and-Paste Errors - https://news.ycombinator.com/item?id=33537539 - Nov 2022 (1 comment)
CSS Nesting - https://news.ycombinator.com/item?id=33424361 - Nov 2022 (2 comments)
Help pick a syntax for CSS nesting - https://news.ycombinator.com/item?id=32248419 - July 2022 (240 comments)
CSS Nesting Module - https://news.ycombinator.com/item?id=28375596 - Sept 2021 (71 comments)
CSS Nesting Module - W3C Editor’s Draft - https://news.ycombinator.com/item?id=27684332 - June 2021 (1 comment)
You Probably Shouldn't Be Nesting Your CSS - https://news.ycombinator.com/item?id=6583109 - Oct 2013 (1 comment)
WebKit to get CSS variables, mixins, nesting? - https://news.ycombinator.com/item?id=2111510 - Jan 2011 (6 comments)
I don't really see an issue with treating JavaScript as something of an "assembly of the browser," in that anyone can make their own language and target it.
Value manipulation (like color changes) are possible in css, but complicated to write and read.
Isn't it interesting how the engine has been implementing new features and generally running on a lot of steam coincidentally since the EU's Digital Markets Act (which will force other web engines on iOS) went into effect?
Or maybe the dev process and community interactions has always been like this, in which case disregard what I just said and feel free to correct me.
Safari took a leading role in interop-2022[0] from the very start. So the change in Safari's philosophy stretches back at least to start of 2022, but they've also led the way on adoption of a number of other web standards like the new colorspaces which they've had since 2021 and which Edge and Firefox still don't support (well, FF has a feature flag)
Even if Safari were to be the best browser ever, I don’t think that would save Apple, so any development effort would be futile (especially compared to lobbying)
I honestly think that developers are very wrong when they think that Safari/webkit is slowing the web down. Yes, some things like lack of notifications etc are very annoying, and they could've been implemented. But I still prefer this approach over the Blink one, where they develop half-baked ideas just to track you better.
While you can be happy only supporting say the last version of all other browsers, Safari requires you to give it years before the marketshare of the new versions are enough that you can migrate to new features, thus making the fact that webkit had implemented those features first completely irrelevant.
Furthermore, the fact it only runs macOS makes it a true pain in the ass to test, you need to have access to an apple machine to test it, be it virtualized or remote, which sucks because even Edge has support for Linux at this point.
Even worse is the fact that there are indeed a lot of features Apple simply refuses to implement, specially related to PWAs, which has slowed down the adoption of PWAs by at least 20 years, ane that's if they ever make a comeback after the crippling Apple did to them to maintain App Store supremacy.
I could go on and on and on and on. Webkit is great sometimes, but Safari absolutely sucks and has been slowing down web development ever since IE stopped being a problem for most developers.
https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-a...
One of the main reasons I never used CRA for my miniprojects was because the first thing I always wanted to do was set PostCSS up with nested CSS support which was a pain to do in CRA
Should I just bite the bullet and figure out Webpack (or another bundler) from the basics? I feel like that will be inevitable at some point anyway.
But I've realized a lot of my projects can actually get by pretty far with just vanilla html/css/js and a good reset.css so I have a template for that that I continuously update and I've actually found that to be the most productive. Though that's likely a function of not having to learn something new unlike all my other projects
There's been suggestions on the React repo of dropping the suggestion to use CRA from the docs entirely since it's pretty outdated and not really in keeping with React's current philosophies.
Another tricky alternative is to just use TypeScript’s compiler. Combined with the new import maps spec, you can target most modern browsers and skip bundling all together.
But I think the real benefit is that it's much easier to get right than Webpack ever was. You don't need to start by configuring a thousand different plugins, rather, you just write an index.html file, reference the root CSS and JS file from there, and then it can figure out the rest, including all the optimisation/minification details, applying Babel, autoprefixing, using browserslist, etc. If it doesn't recognise a file (e.g. because you're importing a .vue or .svelte file) then it'll recommend the right plugin to parse that syntax, and then it's just a case of adding the plugin to a config file and it'll work.
I'm a big fan of Parcel, which is a very similar tool for zero-configuration builds, but Vite feels significantly more polished.
I did recently find one thing that didn’t work out of the box in Vite, though. I needed to write a web worker, but Vite didn’t package it into a single .js file, so I had to call esbuild directly to do that.
furthermore I suspect a very large % of people do not realize you can actually edit and save your CSS directly with Workspaces.
It'll be about a year or so before I'm comfortable using it in production code (assuming it comes to Firefox soon, and presuming it'll get into Edge by default.)
But a year goes past quickly these days, and at least the clock has started ticking.
As a highlight, Nested CSS doesn't support nested selectors if they both begin with letters, so the "&" is used as divider.
I highly recommend web-dev's check out the last section of the article*: https://webkit.org/blog/13813/try-css-nesting-today-in-safar...
[*: even though, IMO, in this instance it seems like a hack; nesting CSS styles, while the HTML is nested in the opposite direction seems pretty counterintuitive. but having the tool in your toolbox could be useful for other things.]
:is(article) &
That looks hacky at best.The excuse of parsing performance is responsible for so much weird syntax in web standards today. The standards are literally being dragged around by browser vendors' priorities.
I wish they would do it the other way around for once: come up with the cleanest, easiest-for-humans syntax as possible, and tell browser vendors to fix their damn engines. Perhaps this will lead to the development of a new CSS engine that's actually optimized for the latest goodies.
Instead, for the last decade or so, we've only been getting bits and pieces of half-assed imitations of Sass. Better than nothing, of course, but still seriously lacking.
> come up with the cleanest, easiest-for-humans syntax as possible
I'm definitely on the opposite end of this argument. I really think browsers should be focusing on efficient and theoretically rock-solid foundations. The fact that web standards are slow to evolve and become adopted is a feature, not a bug. If you visit a create-react-app project from 2 years ago you probably couldn't get it running today. I would like a web where a hand-made site from a decade ago still worksThe global web standard should be reliable and efficient. Syntactic sugars should be left to the ecosystems and only adopted when they don't confer performance tradeoffs
Parsing performance of the type they're talking about is an algorithmic fact, not an implementation problem.
Your suggestion is like telling engineers to fix the laws of physics.
Even if it were a law of physics, engineers can often circumvent laws of physics using smart caching and other tricks.
We've been waiting for this feature for decades already. It would have been better if they'd just invested a couple of more years to come up with a better parsing algorithm before standardizing a halfway implementation.
The problem is really law of physics-ey. But performance impacts (even naively implemented) were never presented for public evaluation.
In the end having the runtime be fast is likely more important than perfect syntax (as we can still pre-compile via better syntax), but the actual numbers and real world use cases matter a lot.
Are these worst case performance scenarios actually realistic or common? I didn't see anybody speaking to that, but also haven't followed this issue in years. I have seen on a lot of the web standards discussions that many of the contributors will pose theoretical worst case situations as something that should meaningfully impact design of a feature, when those worst case scenarios are extremely rare and unrealistic in practice.
W3C has zero leverage over the browser vendors. If they tried to do this the end result would be the same thing that happened to XHTML: the browser vendors would tell them to pound sand and announce that the de facto CSS standard would now be maintained by the WHATWG.
> Because of limitations in browser parsing engines, you must make sure the nested selector (.bar in the above example) always starts with a symbol.
How hard can it be.. I know that is always easy to say from the outside but in this case I don't understand why the refuse to implement it. Just labelling it as a performance problem doesn't say much because why should it impact performance to check whether there appears another rule with an opening "{" after it.
Imagine a CPU that is fast but has no concept of stack, so no recursion/callstack for you. You can simulate it through registers, but only as much as register pressure allows in a finite register file. Allowing unbounded call stack requires changing the class of a CPU to the one that has stack (and is slower, due to analogy is incomplete).
In the same way, &-less grammar changes the class of a parser required to parse it. You can’t simply adjust the existing one. In the end it all boils down to the amount of dynamic allocations and backtracking required for parsing the same megabyte of css.
Edit: nothing substantial was said about actual numbers, at least from what I’ve read. It’s a common sense that seems nobody has tested (in this particular case).
All of these questions and quandaries only exist because the "&" is optional. If it were simply required, there would be no ambiguity to humans or to parsers.
I'm happy about this feature, but they don't really elaborate on what these "limitations" are, except a passing reference later on to "making the parsing engine slower".
Anyone know what the issue is exactly? Why can't they implement it the other way without making the parsing engine slower?
We only need an autoupdate feature for Safari. Badly. It’s the only not evergreen big browser, to my knowledge.
So you don't need to use nesting in your code if you don't want to, but can still take advantage for smaller minified css files using a transpiler.
> "starting the nested selector with an identifier is invalid"
Do we have inheritance already?
Pseudocode of what I mean:
.info {
font-size: 8px;
}
.news extends .info {
color: black;
}
So news are displayed in an 8px black font. .info {
font-size: 8px;
}
.news {
color: black;
}
<div class="info news">asdf</div>
or maybe .info {
font-size: 8px;
}
.news {
color: black;
}
<div class="news"><p class="info">asdf</p></div>
or even .info, .news {
font-size: 8px;
}
.news {
color: black;
}
<div class="news">asdf</div>
but you've got to use LESS/SCSS for true 'extends' type functionality. vanilla CSS is more focused on inheritance.If that is all we have, then I will just stick to css variables:
:root {
--info-font-size: 8px;
}
.info {
font-size: var(--info-font-size);
color: grey;
}
.news {
font-size: var(--info-font-size);
color: black;
}Sass itself has a huge amount of features... is the expectation that we should just adopt a Sass implementation into the browser or something?
.some-class {
color: red;
&__child {
color: blue;
}
}
Which compiles to .some-class {
color: red;
}
.some-class__child {
color: blue;
} dialog {
background-color: white;
color: black;
input {
width: 200px;
}
}
Doesn't work.Very happy to see something major like this being adopted.
Oh man... let the asteroid come.
I'm currently writing a toy "javascript" bundler. I implemented a CSS parser in the past (mostly for linting) and it took me a few hours. Trying to do the same with SCSS made me give up halfway. The test suite was >6000 tests or so and I got up to about 3000 or something, but it gets harder the further up you go. There's lots of other people in Github that are smarter than me and had the same experience, leaving their parser halfway finished. There's a lot of smart stuff in SCSS, and that is perfectly fine for a compile-time tool, but it's not something that's fast enough for a browser, or simple enough that can be added quickly to their current parsers.
I use Vite and PostCSS and a bevy of linters, image processing tools, even for CSS-only projects because they're so fast and generally so good at what they do that it'd be silly not to. I used to hodge tools together with Makefiles but Vite in particular has made the setup for all this stupid-simple.
I make changes, 100ms later Vite deposits a new, optimised build into my Django static dir.
There are [increasingly few] times when it's just nice to just write CSS and I guess unifying nesting will make that nicer, but I don't think there are tangible benefits over "flat" production output.