I personally never ever ran into any problem, when I myself named CSS classes and that is because I automatically think about the future and whether a name could conflict with something else, instead of being lazy and typing 3 characters and thinking I did my job. I am simply careful and use prefixes and give unique names, so that it has such a low chance of someone else using that CSS class name, that it simply never happened in practice. So from my personal experience all that mumbo-jumbo about CSS name collisions comes from people not being careful and is a "house made" problem, not a problem of CSS. I never had any need to use JS to do what is CSS's job.
Using JS for doing something CSS should do is furthermore dangerous, since clever people deactivate their JS or block it partially. For me personally, your (not you personally, but you in general, anyone who reads this) JS better comes from your own domain, or it will be blocked by default. If you can live with people seeing your website utterly destroyed by its inability to apply style, then OK, do the styling in JS.
But I've also been writing CSS since 1997. I've deployed CSS to sites like walmart.com, nfl.com, mlb.com, starbucks.com, twitch.tv, etc. Some of these sites have a lot of third-party widgets on them. I can confidently say that the (multiple) issues with CSS are not a "just do <simple thing X>" type of problem.
I'd go so far to say that almost no (real) problem is that type of problem. Maybe problems that are mostly inconsequential, sure.
Otherwise I do think that the naming collision problem is really easily fixed.
SASS seems to solve most of the problems i would have with writing basic CSS.
Angular implements a polyfill for this. Every angular component has 3 files html, ts, (s)css, and the styles in the components css file are automatically scoped to just the component they apply to. It takes away all the stress of global css selectors, and if you want to share styles you can just have a library of shared styles and import them via scss. It's honestly heavenly and I haven't thought about conflicting selectors in years.
Very typically, for a given app and page the styles of individual elements and components are not independent. They also depend the app theme, app section, layout area, component group, etc. The element fits the component. The component fits into the section, the section fits into the page. The specific relationships in a particular case are different of course. Styles are visual and the idea that a component on a page has nothing visually to do with the rest of the page is wrong.
The typical scoping rules of programming languages doesn't fit that well here.
To the extent some styling solution encourages you to treat styles that are dependent as independent, that's not a good or useful thing.
(You can also relatively easily implement your own, because JS :))
My point is, when it comes to visual styling, you inherently have a shared visual context.
The post I was replying to was concerned with the "global" nature of CSS.
I'm pointing out that this is inherent to the problem space. You have to deal with it whether you use CSS, code or any other mechanism to style.
Does the annoyance primarily center around the fact that styles cascade to child elements? Hard to tell from the article.
Let's say you wanted to pull in a button from Bootstrap for one part of your page, a button from Material UI elsewhere, a button from Semantic UI elsewhere, etc.
These things are made to be reusable right?
What are the chances you can do that without issues? Do you think any of their style rules/selectors would clobber each other? What about the base/assumed CSS that they all most likely require? What about components more complicated than a button? Without actually trying it, how much confidence do you have in your guess, vs. your assumptions about importing other things (like functions from npm modules)?
Good software is reusable without worry.
I just spent the whole day trying to fix compatibility issues between different versions of npm libraries transitively imported in a project. Reusability in JS is a joke.
As a primarily JS/React developer, I think there is irony if JS is held as a good design pattern in comparison to CSS with respect to reusability. Inasmuch as what are being called CSS "workarounds" are in fact workarounds, so too has been the case with JavaScript itself. I am old enough to remember jQuery and Prototype colliding over the dollarsign namespace.
Don't get me wrong. I am not a JS (or CSS) hater. I think these "workarounds" are more than adequate in making these technologies easy to work with. Which I suppose is sort of my point. I see a lot of overengineered codebases with Byzantine solutions to relatively simple problems.
Also, to parent poster:
> Let's say you wanted to pull in a button from Bootstrap for one part of your page, a button from Material UI elsewhere, a button from Semantic UI elsewhere, etc.
1) First of all, don't do this. Perhaps you were just saying this to make a point, but obviously don't include 3 monolothic libs with overlapping functionality in order to implement 3 things with the same functionality.
2) It sounds like your problem with this is more with the libraries themselves. When I write a component, I always namespace it myself. Obviously, if libraries are properly namespaced, then you could easily include buttons from three separate button libraries.
I've had this problem with JavaScript-before-npm-existed, Python, apt, Homebrew, Portage...
nix package manager
The problem:
I use X to create an object with library A v1.0.
I use Y to create an object with library A v2.0.
These objects are not necessarily compatible, so X and Y have problems communicating.
I would be very surprised if you told me nix or stack inherently make objects from multiple versions of the same library magically compatible with each other.
Feel free to close issues like this one if I'm wrong: https://github.com/NixOS/nixpkgs/issues/30551
How would objects created from X and Y can reach each other and communicate when X is not dependent from Y or otherwise? You need global mutable state or your own code witch depends from both X and Y is somehow connecting them.
So one top thing FP movement argues against is global mutable state so of course you don't have that ...Unless you are wrapping some non-FP thing like QT...
And if it's your own code it shouldn't be different that Y creates B:s instead of A v2 since your code is aware from two different versions anyway.
Do you see any weak points?
It has different functionalities.
I live in the real world where it's used almost exclusively by programmers.
Whether technically it's a programming language or not is tangential.
It's off brand, but the technology is roughly the same.
Another game: https://thenextweb.com/dd/2018/05/08/some-madman-built-a-mar...
But a limitation isn’t necessarily bad, and is often good. Finding the language of least power (ie it is just powerful enough to express the sorts of things you want, and no more) is very useful for safety and productivity, but in CSS’s case it seems like it’s no longer powerful enough to express all the things its users desire.
This just is not true. It may be your opinion, but it is objectively false, particularly in the context of this discussion.
SQL is one, HTML too.
They both tell a computer what to do.
Emacs lisp also has lexical scoping. It optionally had it for a long time using cl.el with lexical-let and friends. It now has it as a file-local variable read by the compiler/interpreter.
I also don’t understand what you’ve written at all. You say “Nowadays it does support semantic scoping” but semantic scoping isn’t really a thing (as you next write lexical scoping, I assume you mean dynamic scoping), but the words “nowadays,” “but,” and “still” imply that you are talking about the new kind of scoping (ie lexical) and comparing with the old (dynamic, which you cal lexical???).
> Imagine a programming language that only had global variables. You have to carefully name your variables using complicated conventions in order to avoid any conflicts or unexpected behavior. Even your functions don't have local variables; there is no lexical scoping. Any function can overwrite or mutate what any other function is doing inside. There is no real encapsulation.
That simply isn't true; CSS specifies a bunch of declarative rules, which statically evaluate. Though the evaluator may be stateful, reasoning about how the properties for each document node are determined doesn't require state. It requires reasoning about the targets of the rules, and when they overlap, about their relative scopes and priorities.
But it turns out that we're using it and CSS and JavaScript to build full blown applications. So, because we're trying to solve problems with applications rather than documents, we have to map the problems of application programming onto it.
So, to build an application, we run into problems CSS wasn't designed to solve (being a not-programming language.) Whether it is or isn't a programming language is irrelevant - to solve our problems (writing applications), we have to treat it as if it is.
<StackPanel>
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red" />
</Style>
</StackPanel.Resources>
<TextBlock Text="Red" />
<StackPanel>
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Green" />
</Style>
</StackPanel.Resources>
<TextBlock Text="Green because the default style was reset by the nested container" />
</StackPanel>
<TextBlock Text="Red again because the nested container scope has ended" />
</StackPanel> <Box
p={5}
fontSize={4}
width={[ 1, 1, 1/2 ]}
color='white'
bg='magenta'
>
Box
</Box>
It uses a CSS-in-JS library under the hood to translate that into a CSS class for each unique combination of styling props.I’ve wrote the above example because it shows a possible solution to the stated problem, i.e. how to introduce namespaces for styles without also introducing a full-blown programming language with scopes and variables. The exact syntax can be replaced making it more compact and easier to read.
Compared to this mostly-immutable scoped dictionaries, way more things can potentially go wrong with code, regardless on the programming language.
You have to carefully name your variables using complicated conventions in order to avoid any conflicts or unexpected behavior.
Even your functions don't have local variables; there is no lexical scoping. Any function can overwrite or mutate what any other function is doing inside. There is no real encapsulation.
After you've done this perfectly, your application gets bigger and you start wanting to reuse third-party modules made by other developers, because they've already solved some of your problems.
Uh-oh: they didn't follow exactly the same conventions, and now things conflict. Or their variable names were perfectly unique in their own code base but not when combined with yours (or when combined with several other third-party modules).
This language is CSS and is why people are so fed up with selectors. Even "scoped" selectors really aren't lexically scoped in the sense that other languages handle scoping... it's still just another naming convention hack.
I use CSS-in-JS because CSS wasn't designed to be a language that survives attempts at modularization, third-party code sharing, etc. No sane programming language attempting this would only have global variables. So, we throw out the selectors part of CSS and keep the rest, at least for now.
Nobody using CSS-in-JS thinks this is an ideal situation. Nobody wakes up thinking, "oh my god, I need to put my CSS in my JS, it would be perfect." We're just trying to deal with the hand that's been dealt.