The Case for CSS
I’d like to offer a quite critical viewpoint here. I’d like to take the position of the end user, not of the application developer. The actual user of our application benefits when we have quick load times and excellent rendering performance. No questions.
Repeat, Repeat, Repeat
Too much Flexibility
The original concept of dynamism in pure CSS is to toggle CSS classNames and HTML attributes not changing the “content” of the actual classes. Unfortunately exactly this aspect is not prevented by most solutions client side CSS generation. Responsibility for this is added to the application developer. Conclusion: To make CSS-in-JS successful for server side rendering we should limit its features so that we are ideally able to do most of the features during deployment.
Multiple Invalidation of Document Styling
Browsers are highly optimized for the rendering of static documents. HTML is still mainly a document container. Interactivity was optimized for either for:
- changing classnames or attributes
- changing inline style properties
- adding, removing & modifying elements
Something which is pretty radical and therefor “expensive” for the runtime, but is probably not super obvious, is to add/modify/remove stylesheets to the document. We dealt with this issue years ago during the development of the qooxdoo framework. Most browsers work with some kind of compiled document stylesheet. There is a lot of caching and building of style trees involved in making the previously mentioned interactive mutations as fast as possible.
When we are adding new stylesheets, we are invalidating the compiled style information of the document. When each component is compiling its own CSS and adding it into a style tag this is invalidating this cache and re-evaluating the selectors and document nodes a few times. This adds a lot of pressure to these browser subsystems. (I can’t wait to hear that something has been optimized in recent years, but I did not heard about that yet.)
Flash of Unstyled Content
No styling specific tooling
display, syntax highlighting of errors e.g. for simple typos like
rgb(0, 0, 0, 0.5), linting with tools like stylelint, etc.
Further there is some kind of lock-in. You are actually betting on the specific syntax and functionality. Right, this is somewhat comparable to choosing Sass, Less, Stylus or PostCSS plugins. But generally the ecosystems around CSS-in-JS are far smaller than the previously mentioned more classical approaches. Try counting the possible alternatives. Wait a few weeks for adding additional candidates to your list.
No delegation of CSS possible
In most larger development teams the implementation of stylesheets could be delegated to more experienced CSS developers. That everybody can be done by everybody: One of the biggest lies in our industry. Specialists can handle CSS cross browser issues and layouting details much easier and faster than most SPA developers. These should better focus on topics of overall application architecture, data flow, performance, etc. If we could split development work into two blocks which are implemented by more experienced developers — why wouldn’t you do that?
Benefits of pre-generated CSS files
So what are the benefits of not doing fancy CSS-in-JS but keeping a more traditional approach:
- CSS Modules allow for sandboxing of components and different application views.
- Adding prefixes can be implemented with the largest and best database from Can I Use without any performance and size side implication on the client side. Don’t fall into the assumption that some basic vendor prefixer is capable of doing nearly the same.
- Variables, conditionals and loops are fully resolved during deployment. Everything PostCSS or Sass can do is strictly limited to something which do not require (or even are capable of) access to runtime state.
- Excellent combination with SSR as both HTML and CSS are statically produced beforehand and send to the client. Parallel loading of required assets, no flash of unstyled content.
- Full CSS tooling available with excellent editor support, linting, auto completion and no lock-in a specific syntax.
- Preprocessors have access to the file system. They are able to query referenced assets e.g. image dimensions, automatic SVG spriting, generating icon fonts based on usage patterns, etc.
- Make us of a great number of experienced and productive HTML/CSS-only developers who can easily build cross browser layouts and designs. Modern SPA are not just logic and data but also modern visuals and animations.