📜 ⬆️ ⬇️

About the advantages of embedding CSS in JS

This post is a detailed answer to the questions from this conversation on Twitter . The original author, Sunil Pye, is the author of the relatively popular glamor library and works as a developer on Facebook.


How is Javascript more convenient than CSS? How does writing CSS inside JS make it more supported?

I would be happy to talk on this topic. I’ll say right away that CSS-in-JS solutions have overhead, but usually this price is justified by the advantages they bring. Sometimes they can be useful, but it also does not mean that CSS-in-JS should be used always and everywhere.


So, the most important thing in CSS-in-JS (cij) is CSS selectors. The greatest advantage of cij is that computers can generate these selectors automatically. Convention type OOCSS, etc. good in principle, but they are based on hand-written selectors that make it difficult to ensure uniqueness in the common namespace, because there is always a chance for intersection. If it does not happen now, it can happen after three years, when your team grows and circumstances change. This situation is exacerbated using third-party libraries. Limiting the scope of CSS selectors can also be achieved using CSS modules that are popular for this feature.


However, with all these approaches, selectors are very difficult to statically analyze and find which ones are broken (or contain typos), which means that they will have to be manually checked during the code-review process, which will decrease the team’s effectiveness. We must use the help of computers and not rely on the impeccability and inerrancy of people (because it is not). CSS-in-JS allows you to automate the generation of unique selectors and identifiers.


In addition, enhanced control over CSS selectors opens up new features that were not easily available before. For example, we can elementary implement the extraction of critical CSS by matching blocks of HTML with the styles they need, so that we can load onto the page only 1-2 Kb of CSS that is needed for the initial display of the page. Without any runtime! Gatsby and Next type frameworks are actively used to improve performance in projects based on them. They embed critical CSS directly into loadable HTML simply because it weighs so little that it will be better than an extra query blocking the page loading. This significantly reduces the time of the initial page rendering. Moreover, it also helps to solve the problems of the size of the loaded Javascript! The benefits come from applying critical CSS, as well as using dynamic import() , splitting code, and removing unused code. (In contrast to the ever-growing legacy of style files, in which developers just add a new code, being afraid to touch the existing one. There are some analytics on this topic .)


A similar situation with the implementation of themes. Did you know that CSS variables , even being a very interesting thing, did not soar up to those usage scenarios for which they were originally intended, and all because the fallback methods for old browsers turned out to be either very complex or inferior? This means that they are usually used as global constants, but very rarely as variables, the value of which is determined in the browser dynamically. Having runtime for working with CSS means that you can transfer values ​​from JS to styles, making it possible.


In fact, you will like it: you can, finally, honestly use CSS variables in all browsers, that is, native features without runtime in browsers that support them, and a special runtime for older browsers. (I wrote more about this here , and - if I understand correctly - this is the only library that has achieved this).


In a complex SPA situation with a bunch of components and asynchronous resource loading, such as scripts and styles, you cannot guarantee the exact order of loading styles, so either you have to create some runtime solutions to guarantee the order of styles, or just use !important , even if you stick to some kind of CSS methodology . For example, you have an element with class=“ab” , but the classes a and b defined in different style files, you cannot be sure of the final form of the block, unless you have clearly specified the order of the style files. The Facebook code base contains thousands of uses !important , even though the code was written by qualified programmers using the SOLID principles and good interaction with the design team.


It often refers to handling CSS as if it were Javascript - given that 10 years ago we had already solved similar problems for JS - libraries and modules registered themselves in the global namespace ( $ and the like) and we had to be quite careful with the order scripts in html. But we are not stuck there forever - now we use modules, and the assembly systems sew them together in guaranteed guaranteed order. This is simple and transparent to us.


Watching real projects, I also noticed that you can still use traditional architectural approaches (such as OOCSS or SMACSS, etc.) in the CSS-in-JS world - elements of those architectures are represented here as JS objects, instead of blocks, a selector + styles I adhere to this approach and it works for me well. Here you can read more about it.


I am also well aware of the shortcomings of CSS-in-JS. In fact, this is why there is no single “canonical” library that represents CSS-in-JS - this is a range of different solutions, from vanilla static CSS on the one hand to fully dynamic libraries, such as styled-components on the other. Pre-processors like SASS or LESS may seem perpendicular to this spectrum, because in theory they can be used by any of these libraries at the discretion of their authors. Each of these libraries has its drawbacks - some are engaged in extracting styles at the assembly stage so that there are no costs in runtime, some are focused on the correctness or convenience for developers, others are focused on the effective implementation of complex animations, and so on and so forth. This diversity is a natural reaction to the need for different solutions for different work tasks, in an overly rapidly developing industry. And this happens not only with libraries - web standards developers (ShadowDOM and others) are valiantly trying to solve these problems too, but their solution also has flaws, the least of which is that they are not everywhere available yet, which makes it unacceptable for use in a variety of teams.


I used to have strong feelings about this, but I have moderated my views over the past few months. It turns out that the truth actually lies somewhere in the middle - it depends on the commands, requirements, time, documentation and many other factors. Moreover, I do not think that this text represents the “final form” of this idea. We need to encourage experiments in this area, so that we can find out what else we can do better, and even embed some of these things into browsers.


PS I realized too late that I forgot to tick the "Translation" checkbox, so I published it like this. Link to the original .


Habr, fix the interface, why can't the translation flag be added after publication?


')

Source: https://habr.com/ru/post/433276/


All Articles