Rendered at 15:24:37 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
wewewedxfgdf 2 days ago [-]
My final conclusion about CSS is - program the damn machine.
What I mean by this is STOP every single type of abstraction/library/programming layer for CSS - nothing gets it right, everything causes a problem.
The ONLY way to deal with CSS is program it directly in the way the docs say, never anything else.
There's nothing wrong with using Bootstrap or whatever, and I definitely use JavaScript to program CSS. What I am saying is - no abstractions - no "better way" - no trying to turn CSS into something it isn't via whatever your new abstraction is that can be added to the N other abstractions that other people have made over the years.
Program the damn machine.
coffeefirst 2 days ago [-]
Yes. It’s been twenty years of watching people pick an fussy framework because they don’t want to learn the tool, then struggle to get the results they want because the framework is flawed but they didn’t learn enough to understand how and when to fight it.
And with grid, variables, animation, container queries, modern CSS is amazing. You just need to treat it with a little respect.
wewewedxfgdf 2 days ago [-]
Lots of developers feel they need a library to program anything - got forbid that you should program that actual machine.
ericwood 2 days ago [-]
CSS suffers from one of its original design tenants in that it's very easy to throw some shit at the wall and kind of get it working without fully understanding it. This is especially true for people who have dabbled in it from time to time in their career when absolutely needed. It's rare to see someone sit down and learn it from first principles. It doesn't take long and knowing the basic theory goes a long ways!
antod 2 days ago [-]
I agree. I taught myself CSS1 by reading the spec (it was limited, small and simple). CSS2 was a lot bigger and way more complex but Eric Meyer's Salmon book helped a lot.
One problem (20yrs ago at least) was that for a long time the specs weren't supported very well by common browsers. So everyone just prodded at hacks using trial and error instead of learning it. That approach never really went away even after support improved.
dotancohen 1 days ago [-]
> So everyone just prodded at hacks using trial and error instead of learning it.
And that is exactly why all those frameworks started appearing. It wasn't developer laziness. It was developer sanity.
jgalt212 2 days ago [-]
> CSS suffers from one of its original design tenants in that it's very easy to throw some shit at the wall and kind of get it working without fully understanding it
And dev tools made this feedback loop much faster.
yoz-y 2 days ago [-]
For me nothing beats plain old classes and an external css file. For PWAs I just use lit css within the element, again with classes and plain css. If things cause problems, just figure out why and fix the classes.
paradox460 2 days ago [-]
I've been ranting about this for years, even wrote a blog post[1] a few years ago whinging about it. Nice to see others share the same sensibility
The worst part is that inevitably the frameworks end up being harder to learn than CSS due to feature accretion
tenphi 1 days ago [-]
[dead]
herpdyderp 2 days ago [-]
This is exactly how I feel. Learn how to write CSS! Like you would do with any language!
exogen 1 days ago [-]
Been writing CSS since 1997. Your mistake is thinking that the authors of these frameworks (or their target audience) just don't know how to use CSS correctly. But it's far more likely that the authors know far, far more about the intricacies of CSS and how it works than most developers. These frameworks are almost always developed by people with deep experience in the trenches, who have realized that CSS scales fucking terribly... not because they are misinformed or did anything wrong.
Namely:
- Selectors are a global namespace. Imagine if every variable and function in your favorite programming languages were global and so had to be unique. No modules or namespaces. Developing a system to fix that would be pretty high on my list of priorities... coming up with a cool solution and then people telling me to "just learn the language" would be pretty fucking infuriating, don't you think?
- Several fighting priority systems (did you know about newer ones like @layer?). And equivalent priority falls back to source order - OK, so how do you square that with dynamic loading? Some navigation paths through an app would inject some CSS first whereas others would inject other CSS first. Good luck!
pjaoko 1 days ago [-]
> Selectors are a global namespace. Imagine if every variable and function in your favorite programming languages were global and so had to be unique.
A selector is not not a variable or a function. CSS has functions (e.g translate) and it has variables, which are both distinct concepts in the language from selectors.
> No modules or namespaces.
CSS is not supposed to be a turing complete general purpose programming language. Why would you need namespaces and modules to style up HTML tags?
exogen 1 days ago [-]
Because many web sites and apps aren't as simple as "my first homepage" and don't only consist of first-party code. Think component libraries. Reusable code. Content management systems. Third-party SDKs (chat widgets, support widgets, payment widgets like Stripe, etc.).
One of my earliest webdev jobs was at a company whose product was a widget you could add to your site by adding our `<script>` tag. Thus, our CSS needed to coexist with the first-party site's, not to mention any other third-party widgets on there. In other words: the same exact reason you need modules in traditional languages.
bryanrasmussen 1 days ago [-]
It's true in a case where you are doing the described thing you will need to come up with your own module system and ways to not step on other people's stuff but it isn't actually difficult. Although I have noticed some stories recently were quite big companies evidently didn't put in the work to keep from messing up other people's stuff.
Of course one drawback with that is you are also depending on developers and content managers at sites following your documentation on how to use your products, which is a different problem.
on edit: obviously if you have been writing css since 1997 and one of your first webdev jobs was this kind of thing, things were much more difficult back then. I did the same sort of thing in 2014-2015, not particularly difficult to make work. I worked web dev since 1999, first job was dynamic generation of web sites and other media from single source data.
lee_ars 21 hours ago [-]
> A selector is not not a variable or a function. CSS has functions (e.g translate) and it has variables, which are both distinct concepts in the language from selectors.
Congratulations, you have attacked the analogy rather than the argument.
exogen 1 days ago [-]
> A selector is not not a variable or a function. CSS has functions (e.g translate) and it has variables, which are both distinct concepts in the language from selectors.
That misses the point. They're identifiers scoped to the entire document - the same way global variables and global functions are identifiers scoped to an entire program.
themanualstates 21 hours ago [-]
- You could use 'CSS Modules' or 'CSS Module Scripts'; it's CSS but the classnames and animation names are locally by default.
- Rule priority is decided by selector specificity also.
HTML has also answered your these needs with the locally scoped ShadowDOM.
bryanrasmussen 1 days ago [-]
>Selectors are a global namespace.
what does this mean? Selectors are how you query a particular element to apply styles to it, I think what you mean is that selectors as a query language does not allow you to query any element from any other element the way you can with XPath but in many use cases you need to start querying globally.
but we can also see that the only way that querying from element to any other element makes sense if you could do something like (pseudo XPath / CSS abomination coming up)
which sure, I have, some very few times thought boy it would be nice if I could do more involved context selection in CSS based on an elements surrounding DOM than sibling axis and the like offer.
however
> Imagine if every variable and function in your favorite programming languages were global and so had to be unique.
yes, I know you are not saying that variables in CSS need to be global. However I think you have perhaps not internalized yet how CSS variables and scoping rules work have created a situation that allows for often elegantly solving problems that one might wish one had a more powerful query language to handle.
The following is of course not elegant, but is an example of how we change the design of .someclass based on having an ancestor mainEntry that has an empty .headline using variables.
>OK, so how do you square that with dynamic loading? Some navigation paths through an app would inject some CSS first whereas others would inject other CSS first.
yes I've run into this situation before, however for me it was a framework issue not a css standards issue, and it sounds to me with phrases like "navigation paths" and "app inject some css" that it was a JS framework that made you unhappy and not actually the state of Web standards.
D'oh! right, got lost in trying to think up a situation nowadays where you can't really do a meaningful query that takes all DOM context into account. Not sure if all edge cases are not actually handled by has and is, actually.
easyThrowaway 1 days ago [-]
> However I think you have perhaps not internalized yet how CSS variables and scoping rules work have created a situation that allows for often elegantly solving problems that one might wish one had a more powerful query language to handle.
As you already said, this approach would work fine if you had no external payloads that inject their own HTML and CSS on the page, either at runtime or by being loaded by other modules in a CMS.
It also breaks when your :root selector is being polluted by overly generic variables by your platform, like in the most recent versions of Wordpress.
AlienRobot 1 days ago [-]
The problem is not CSS per se, but HTML.
HTML was designed to be a document language, like a PDF, but worse because it has no absolute positioning so text just changes shape when you change the width.
Almost every website does NOT follow the "document" paradigm but an "app" paradigm with navbars, sidebars, panels, etc. None of these things fit the model HTML was specialized for.
If HTML/CSS were for those things, we would have had scoped rules for classes day 1.
exogen 1 days ago [-]
Exactly. The problem is the platform has not kept up with the way it's used in practice. Features are added with strange priorities, and obvious blind spots ignored, leading to it being under-developed in many areas, and over-developed in a handful of others. We get vendors working on weird stuff like Web Bluetooth before obvious things like element anchoring (finally, yay... but still just a Working Draft) and reliable element position tracking (still a huge pain).
There are still no affordances for many things, so people have to invent their own solutions.
AlienRobot 1 days ago [-]
I've always had the impression that the "problem" at its crux is that people worked around HTML/CSS limitations. A recent article about IPv4 gave me the same feeling.
When faced with a widespread standard that is sorely lacking, instead of patching the standard globally, people come up with their own workarounds. This accumulates until the whole thing becomes a conceptually "pure" core under a transfigured mess of patches to make it work the way the modern world needs it to work.
For HTML, I feel that PHP and Web 2.0 did unspoken harm to it. A lot of things that are done by server-side rendering (and afterwards in client-side rendering) should just be features built into HTML from the start. Templates, themes, widgets (panels), components, etc. Now we have "templates" and "components" but neither of these terms mean something in HTML that actually does what you would expect from a templating language which is critical of almost every website.
I mean, am I crazy to think that if you have 2 webpages that share the same navbar, you shouldn't need a build step or special program just to handle this use case in a way that is maintainable? It should just be built into HTML? Javascript isn't a solution to this because that means the website is unusable without Javascript, and that sounds stupid. You need to enable Javascript just to have a navbar? Or you need a whole SSR just to avoid having to copy-paste the navbar? Or a build step? How did we keep using this thing for 30 years?
I feel like because developers could just do this with PHP/JS, these basic features never made into the pure HTML language.
The weird thing is that these languages still get features, just not any features that makes it more powerful at building simple things. HTML has video, web assembly, CSS has animated fonts. But you still need a separate program if you want the same navbar everywhere.
jjpones 2 days ago [-]
I've loved tailwind for the colocation of the component HTML and its corresponding styling (never gave up on traditional CSS though!), but with scoped styles I might start leaning back to traditional CSS.
eviks 1 days ago [-]
The only way to deal with a poorly designed system is NOT giving up, but engineering your way out of it
easyThrowaway 1 days ago [-]
I mean... sure, just tell me how to write a fully responsive landing page straight from a PSD file by the marketing dept in roughly less than an hour without using Bootstrap or, for goodness sake, Tailwind and I'm ready to drop any framework and write "bare metal" (Ah!) CSS.
I'd also like if anyone could look at the specifications for CSS, ideally for Grid, especially the `grid-template-*` and `grid-auto-*` subset of rules, mixmaxing and gotchas and tell me what CSS exactly is right now, So I can avoid turning it into something that is not.
atoav 1 days ago [-]
Also: web layouts are meant to look different on different screens. I had to program my own layouts from scratch for embedded devices and games before. And that occasionally made me wish for CSS.
CSS is fine. Most people just never learned it.
tenphi 2 days ago [-]
Happy to take questions! I built this because I kept hitting the same wall: CSS state resolution is opaque when states overlap, and extending components means mentally re-deriving the whole selector matrix every time.
Some topics I'm curious what people think about:
- What’s the one thing this doesn’t cover that you’d expect it to?
- Does the syntax feel natural to you, or did you find yourself confused by anything?
- I'm looking for edge cases: what kind of complex selector scenario would trip this compiler up or be impossible to express with this model?
AMA—happy to answer any questions about the tool, the implementation, or the design choices.
efortis 2 days ago [-]
The simple solution is :enabled:hover. For example:
For every complex problem there is a solution that is clear, simple, and wrong.
chrismorgan 2 days ago [-]
This sounds interesting, but I’d need to think about it more so I could picture how things fit together as they get more complex and different styles logically overlap. This looks to head in the utility direction possibly too far for that to work nicely. But it may well work better than I’m initially imagining.
Unfortunately I can’t give it more attention now, because I should have gone to sleep a couple of hours ago…
—⁂—
Another approach entirely is to embrace last-declaration-wins, by :where()ing everything:
I’d be interested to know which approach performs better once you have altogether too many elements and altogether too complex selectors. I suspect the :where() would win, but that the difference would be impossible to detect in any sort of realistic load.
tenphi 1 days ago [-]
It took me years to picture "how things fit together as they get more complex and different styles logically overlap". I hope we didn't lose you :)
Considering the `:where` approach, I would say it might work most of the time, but it doesn't cover cases where you don't need to set a value, or when your condition requires a more complex selector (e.g., a parent/root context). It was very important for me to support all cases, so I don't feel limited by the tool.
chrismorgan 1 days ago [-]
> cases where you don't need to set a value
I don’t know what you mean.
> when your condition requires a more complex selector (e.g., a parent/root context)
I don’t see the problem. :where() takes a <complex-selector-list>.
tenphi 1 days ago [-]
For example, I want to set (override the inherited one) a custom property by default, but not when some condition is met. Yes, it might be solved with `inherit`, but in other cases `initial` should be used. I prefer not to define anything unless necessary, so the default (from the cascade) can still be used.
You are probably right about `:where`, but using it with complex selectors might noticeably affect the performance, as it does with `:has`. Didn't run any test for `:where` specifically, though.
Also, we apply lots of styles to the same elements, most of which are overridden.
Another issue is using a different set of longhand/shorthand properties for different states that won't be correctly overridden in this approach.
So it might work pretty well in most of the cases, especially simple ones. But it's definitely not better than mutually exclusive selectors.
chrismorgan 23 hours ago [-]
Ah, unsetting. I get what you’re pointing at there, but my immediate reaction is surprise that this is relevant for your approach, which seems to be all about avoiding situations where that has an effect in the first place. Utility styles and explicitly shunning the cascade.
On :where(). It’s easy to see why :has() can tank performance: it’s doing a whole new complicated thing. :where() is a good deal simpler, and this specific form of it (where it’s the entire selector) has only the effect of zeroing specificity. I’d be mildly surprised if the performance difference from wrapping an entire selector in :where(…) was measurable even in a worst-case synthetic document.
tenphi 4 hours ago [-]
You are right. I doubt it can cause any issue by itself, but with complex states it might end up being `.class:where(.root .class:is([state1], [state2])`. Still, it should be fast enough.
Anyway, I prefer a fully deterministic approach that eliminates any potential issue.
`revert-layer` is just `revert` for layers. It's not a lack of value.
Tasty doesn't fight cascase; it fights ambiguity in source order and specificity.
Cascade might still be useful for many things.
grebc 2 days ago [-]
I’ve made some gnarly custom forms over the years but never quite run into the problem you’re describing.
These days if starting a greenfield web app, each page has its own style/css sent in the head tag.
Because it’s usually just base layout + page specific styles/overrides then it barely adds any overhead in the scheme of things(couple of extra KB).
Maybe the base layout could be moved into a static file to be cached but whatever, it’s already ridiculously quick to render plain html/css.
tenphi 1 days ago [-]
If you lack a solid component system, you likely do not require complex tools to manage CSS.
Pikamander2 2 days ago [-]
Personally I just increase the specificity as needed.
.thing
.thing-container .thing
html body .thing-container .thing.thing.thing.thing
tenphi 1 days ago [-]
Great, if it suits your needs. In a big enterprise product, it would be a waste to have so many CSS that are not actually used. Also, maintaining this seems like a nightmare to me.
invalidSyntax 1 days ago [-]
I can agree that CSS is really unpredictable. However ,not being able to put CSS in a file isn't a small change. It makes other people to read the code harder, and mixing css and js just doesn't feel right. But just to keep my self safe, I know how people reacted to react at first. This might be normal in the future. Maybe.
tenphi 1 days ago [-]
Exactly. And we won't find out if we don't try.
Also, specifically, this approach is more JSON-based (compared to other CSS-in-JS). So you can easily put styles into a separate file if you want, JS or JSON. But I prefer defining styled components in a separate file, as `styled-components` recommends.
danielvaughn 2 days ago [-]
I also spent years on the same problem. I was creating a programming language for designers, which was supposed to abstract away the complexity of CSS. Long story short, I gave up.
tenphi 1 days ago [-]
Sorry to hear it. I didn't. And now our designers can tweak the code directly to adjust component styling. They can finally read and edit styles.
tenphi 1 days ago [-]
Actually, most importantly, AI can read and edit styles. CSS is hard enough on its own; adding overrides makes it so complex that it becomes unmanageable at scale.
bryzaguy 1 days ago [-]
Reminds me of styled components. If the goal is generating the selector why not let the body be a string: ```{ Item: "color: red;" }```?
tenphi 1 days ago [-]
Because usually each style requires its own set of states, and raw strings are hard to type (in Typescript). But there are even more reasons.
`styled-components` is just an advanced CSS injector. We used it as an injector in the early version of Tasty.
efilife 1 days ago [-]
> You are no longer just writing styles. You are maintaining a resolution system in your head.
What I mean by this is STOP every single type of abstraction/library/programming layer for CSS - nothing gets it right, everything causes a problem.
The ONLY way to deal with CSS is program it directly in the way the docs say, never anything else.
There's nothing wrong with using Bootstrap or whatever, and I definitely use JavaScript to program CSS. What I am saying is - no abstractions - no "better way" - no trying to turn CSS into something it isn't via whatever your new abstraction is that can be added to the N other abstractions that other people have made over the years.
Program the damn machine.
And with grid, variables, animation, container queries, modern CSS is amazing. You just need to treat it with a little respect.
One problem (20yrs ago at least) was that for a long time the specs weren't supported very well by common browsers. So everyone just prodded at hacks using trial and error instead of learning it. That approach never really went away even after support improved.
And dev tools made this feedback loop much faster.
1: https://pdx.su/blog/2023-07-26-tailwind-and-the-death-of-cra...
Namely:
- Selectors are a global namespace. Imagine if every variable and function in your favorite programming languages were global and so had to be unique. No modules or namespaces. Developing a system to fix that would be pretty high on my list of priorities... coming up with a cool solution and then people telling me to "just learn the language" would be pretty fucking infuriating, don't you think?
- Several fighting priority systems (did you know about newer ones like @layer?). And equivalent priority falls back to source order - OK, so how do you square that with dynamic loading? Some navigation paths through an app would inject some CSS first whereas others would inject other CSS first. Good luck!
A selector is not not a variable or a function. CSS has functions (e.g translate) and it has variables, which are both distinct concepts in the language from selectors.
> No modules or namespaces. CSS is not supposed to be a turing complete general purpose programming language. Why would you need namespaces and modules to style up HTML tags?
One of my earliest webdev jobs was at a company whose product was a widget you could add to your site by adding our `<script>` tag. Thus, our CSS needed to coexist with the first-party site's, not to mention any other third-party widgets on there. In other words: the same exact reason you need modules in traditional languages.
Of course one drawback with that is you are also depending on developers and content managers at sites following your documentation on how to use your products, which is a different problem.
on edit: obviously if you have been writing css since 1997 and one of your first webdev jobs was this kind of thing, things were much more difficult back then. I did the same sort of thing in 2014-2015, not particularly difficult to make work. I worked web dev since 1999, first job was dynamic generation of web sites and other media from single source data.
Congratulations, you have attacked the analogy rather than the argument.
That misses the point. They're identifiers scoped to the entire document - the same way global variables and global functions are identifiers scoped to an entire program.
- Rule priority is decided by selector specificity also.
HTML has also answered your these needs with the locally scoped ShadowDOM.
what does this mean? Selectors are how you query a particular element to apply styles to it, I think what you mean is that selectors as a query language does not allow you to query any element from any other element the way you can with XPath but in many use cases you need to start querying globally.
but we can also see that the only way that querying from element to any other element makes sense if you could do something like (pseudo XPath / CSS abomination coming up)
.someclass[[ancestor::.mainEntry .headline:empty]]
or maybe you would prefer
.mainEntry[[.headline:empty]] .someclass
which sure, I have, some very few times thought boy it would be nice if I could do more involved context selection in CSS based on an elements surrounding DOM than sibling axis and the like offer.
however > Imagine if every variable and function in your favorite programming languages were global and so had to be unique.
yes, I know you are not saying that variables in CSS need to be global. However I think you have perhaps not internalized yet how CSS variables and scoping rules work have created a situation that allows for often elegantly solving problems that one might wish one had a more powerful query language to handle.
The following is of course not elegant, but is an example of how we change the design of .someclass based on having an ancestor mainEntry that has an empty .headline using variables.
https://codepen.io/bryanrasmussen/pen/xbEoabM
>OK, so how do you square that with dynamic loading? Some navigation paths through an app would inject some CSS first whereas others would inject other CSS first.
yes I've run into this situation before, however for me it was a framework issue not a css standards issue, and it sounds to me with phrases like "navigation paths" and "app inject some css" that it was a JS framework that made you unhappy and not actually the state of Web standards.
> or maybe you would prefer
> .mainEntry[[.headline:empty]] .someclass
I don't really know xpath but isn't that this?
.mainEntry:has(.headline:empty) .someClass
As you already said, this approach would work fine if you had no external payloads that inject their own HTML and CSS on the page, either at runtime or by being loaded by other modules in a CMS.
It also breaks when your :root selector is being polluted by overly generic variables by your platform, like in the most recent versions of Wordpress.
HTML was designed to be a document language, like a PDF, but worse because it has no absolute positioning so text just changes shape when you change the width.
Almost every website does NOT follow the "document" paradigm but an "app" paradigm with navbars, sidebars, panels, etc. None of these things fit the model HTML was specialized for.
If HTML/CSS were for those things, we would have had scoped rules for classes day 1.
There are still no affordances for many things, so people have to invent their own solutions.
When faced with a widespread standard that is sorely lacking, instead of patching the standard globally, people come up with their own workarounds. This accumulates until the whole thing becomes a conceptually "pure" core under a transfigured mess of patches to make it work the way the modern world needs it to work.
For HTML, I feel that PHP and Web 2.0 did unspoken harm to it. A lot of things that are done by server-side rendering (and afterwards in client-side rendering) should just be features built into HTML from the start. Templates, themes, widgets (panels), components, etc. Now we have "templates" and "components" but neither of these terms mean something in HTML that actually does what you would expect from a templating language which is critical of almost every website.
I mean, am I crazy to think that if you have 2 webpages that share the same navbar, you shouldn't need a build step or special program just to handle this use case in a way that is maintainable? It should just be built into HTML? Javascript isn't a solution to this because that means the website is unusable without Javascript, and that sounds stupid. You need to enable Javascript just to have a navbar? Or you need a whole SSR just to avoid having to copy-paste the navbar? Or a build step? How did we keep using this thing for 30 years?
I feel like because developers could just do this with PHP/JS, these basic features never made into the pure HTML language.
The weird thing is that these languages still get features, just not any features that makes it more powerful at building simple things. HTML has video, web assembly, CSS has animated fonts. But you still need a separate program if you want the same navbar everywhere.
I'd also like if anyone could look at the specifications for CSS, ideally for Grid, especially the `grid-template-*` and `grid-auto-*` subset of rules, mixmaxing and gotchas and tell me what CSS exactly is right now, So I can avoid turning it into something that is not.
CSS is fine. Most people just never learned it.
Some topics I'm curious what people think about:
- What’s the one thing this doesn’t cover that you’d expect it to?
- Does the syntax feel natural to you, or did you find yourself confused by anything?
- I'm looking for edge cases: what kind of complex selector scenario would trip this compiler up or be impossible to express with this model?
AMA—happy to answer any questions about the tool, the implementation, or the design choices.
Unfortunately I can’t give it more attention now, because I should have gone to sleep a couple of hours ago…
—⁂—
Another approach entirely is to embrace last-declaration-wins, by :where()ing everything:
I’d be interested to know which approach performs better once you have altogether too many elements and altogether too complex selectors. I suspect the :where() would win, but that the difference would be impossible to detect in any sort of realistic load.Considering the `:where` approach, I would say it might work most of the time, but it doesn't cover cases where you don't need to set a value, or when your condition requires a more complex selector (e.g., a parent/root context). It was very important for me to support all cases, so I don't feel limited by the tool.
I don’t know what you mean.
> when your condition requires a more complex selector (e.g., a parent/root context)
I don’t see the problem. :where() takes a <complex-selector-list>.
You are probably right about `:where`, but using it with complex selectors might noticeably affect the performance, as it does with `:has`. Didn't run any test for `:where` specifically, though. Also, we apply lots of styles to the same elements, most of which are overridden.
Another issue is using a different set of longhand/shorthand properties for different states that won't be correctly overridden in this approach.
So it might work pretty well in most of the cases, especially simple ones. But it's definitely not better than mutually exclusive selectors.
revert-layer <https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/V...> may be relevant to the situation you describe. Not the simplest thing, but it’s a tool most don’t know about yet which can do that kind of thing.
—⁂—
On :where(). It’s easy to see why :has() can tank performance: it’s doing a whole new complicated thing. :where() is a good deal simpler, and this specific form of it (where it’s the entire selector) has only the effect of zeroing specificity. I’d be mildly surprised if the performance difference from wrapping an entire selector in :where(…) was measurable even in a worst-case synthetic document.
Tasty doesn't fight cascase; it fights ambiguity in source order and specificity. Cascade might still be useful for many things.
These days if starting a greenfield web app, each page has its own style/css sent in the head tag.
Because it’s usually just base layout + page specific styles/overrides then it barely adds any overhead in the scheme of things(couple of extra KB).
Maybe the base layout could be moved into a static file to be cached but whatever, it’s already ridiculously quick to render plain html/css.
.thing
.thing-container .thing
html body .thing-container .thing.thing.thing.thing
`styled-components` is just an advanced CSS injector. We used it as an injector in the early version of Tasty.