CSS in JS is like replacing a broken screwdriver with your favorite hammer.
There's a ton of interest these days in 'CSS in JS'. The premise is simple: CSS operates in a global namespace, which can result in undesirable side effects, spaghetti code, and extremely difficult to maintain codebases. JavaScript used to do this, and we fixed it by encapsulating everything in modules and using tools like webpack to stitch everything together. And hey look, our JavaScript tools can handle CSS too, why don't we move all of our CSS into JavaScript and encapsulate everything by module!
There is a real problem here to be solved - it is entirely possible to create terrible, unmaintainable, disastrous CSS. In fact, it's extremely common to do so! And don't get me wrong, I love JavaScript... but as a solution to this problem, CSS in JS is like replacing a broken screwdriver with your favorite hammer. Sure, you'll get the screw further into the wall, but you also destroy all of the unique and valuable problems that had you using a screw instead of a nail in the first place!
Key differences between CSS and JavaScript
Let's take a look at some of the key attributes that differ between the problems CSS is solving and what JavaScript is solving.
Structural/Behavioral Vs Graphical
One of the common arguments for "CSS in JS" is that "we thought separation of concerns was important, but look at JSX!". The argument uses this example (which is itself still quite controversial) to argue that clearly separation of concerns is wrong and adding CSS to JS will also improve productivity.
This argument neglects the difference between structural/behavioral properties and graphical properties. Separation of concerns is valuable when the concerns are in fact separate, letting you reason independently about the two pieces. The reason JSX provides an improvement in productivity is that structure and behavior are tightly linked - a large amount of JavaScript logic has to do with manipulating HTML structure, so separating the two creates more cognitive overhead, not less.
Contrast this to graphical properties, which are a very large percentage of what is being manipulated by CSS. Rather than being tightly linked to structure, these are very loosely coupled - this is why one can often wireframe an entire application out before styling it! Moving your CSS into your logic introduces unnecessary coupling, leading to more cognitive overhead not less.
Loose coupling vs tight coupling
The concept of coupling provides another way of thinking about these tradeoffs. It is well acknowledged that designing loosely coupled systems results in more scalability, more maintainability, and easier reasoning. Styling is only loosely coupled with structure - visually similar UI elements can have dramatically different underlying structure, logic, and even behavior. Contrast this to interactive elements, where the logic of interaction necessarily is tightly coupled to the structure it is manipulating.
New Problems From CSS in JS
Visual Consistency
Another key difference between the logical/structural nature of JavaScript and the graphical/visual nature of CSS is the need for consistency. Within the JavaScript world, the more you can isolate and make each component independent, the better off you are. With proper encapsulation, you can even treat each JavaScript piece completely independently, without any need for consistency in their inner workings.
Contrast this to your visual output - if each and every component is completely isolated visually from one another, your site or application will be a disastrous mess! Certainly every component has unique properties, and those properties should be isolated so as not to leak, but there is also a tremendous need for visual consistency across your site. This is one of the core reasons for the CSS cascade, and while a misunderstood and uncontrolled cascade can be disastrous, used properly it is an incredibly powerful tool.
Code Reuse
Keeping things 'DRY' and having reusable code rather than constantly repeating yourself is generally considered a good practice in software development. It enables fixes and changes to occur in one place, rather than having to be replicated a multitude of places throughout a codebase. It baffles me then, when CSS in JS advocates argue for essentially the "copy and paste" methodology when it comes to styling. As was mentioned above, visual consistency across the various elements of your site or application is extremely important. This means that if every component is itself responsible for its own styling, you will end up with tremendous amounts of duplication! What then happens if your brand changes its' design language? If you want to introduce a new theme, or even subtly tweak your application to keep up with modern design practices? You'll end up having to dig into every single component to implement these changes. In the name of "maintainability", this practice introduces a maintainability nightmare!
The Real Answer: Better CSS Practices
Hopefully at this point I've convinced you that CSS in JS is a bad idea, but there is still a real problem to be solved here! This concept arose because there are tremendous numbers of terrible, unmaintainable CSS stylesheets out there. "Append only CSS" and deeply entangled stylesheets where every change is fraught with risk are rampant in the industry. I've been there, and it's a terrible situation to be in! But luckily, there are a ton of smart people who have been thinking about and working on this problem. The real solution is not to apply the JavaScript hammer to yet another problem, but to recognize that crafting your CSS is a real engineering project, one with different constraints and requirements than writing your JavaScript, and that there are best practices to follow to create streamlined, maintainable, scalable stylesheets.
If you're new to this space, some of the practices to check out include OOCSS, SMACSS, BEM, ITCSS, and ECSS. Each of these has a great deal of thinking behind it, and like any engineering problem there is no 'perfect solution', just different sets of tradeoffs. Adopting any of these practices will improve your CSS and help you find your way out of stylesheet hell. The key is to acknowledge that this is an engineering discipline, and that it deserves the attention and rigor of any other engineering discipline.