Choosing a CSS in JS library
Check comments below, this is only my opinion and a choice specific to my use case
We've architected a SPA to be universal-ready. It grew a lot, when we introduced code splitting we realised converting to CSS in JS was unavoidable in order to have pre-rendering and not load all our CSS up front. We've procrastinated on looking at CSS in JS properly, prioritasing immediate business needs, but kept an eye on industry evolutions.
Our CSS solution for components was a CSS companion file per component, imported with style / postCSS loader (with webpack) but no CSS modules: we were missing a tighter coupling between component rendering and styles. We were at the bottom of the CSS and componentization ladder, the following links have influenced us in choosing the right solution for us:
- Christopher Chedeaux, 2015, "CSS in JS" https://speakerdeck.com/vjeux/react-css-in-js
- Mark Dagleish, 2015, "The case for CSS modules" https://www.youtube.com/watch?v=zR1lOuyQEt8
- Cristiano Rastelli, 2017, Cristiano Rastelli, https://www.youtube.com/watch?v=bb_kb6Q2Kdc & https://speakerdeck.com/didoo/let-there-be-peace-on-css
- Daniel Steigerwald, 2017, "CSS in JS: The Argument Refined" https://medium.com/@steida/css-in-js-the-argument-refined-471c7eb83955
- Ludovico Fisher, 2017, "Comparing CSS in JS solutions" https://www.ludovf.net/blog/comparing-css-in-js-solutions/
- Mark Dagleish, 2017, "A unified styling language" https://medium.com/seek-blog/a-unified-styling-language-d0c208de2660
There is a vast number of libraries to choose from: https://github.com/MicheleBertoli/css-in-js.
CSS modules would have worked for us, and would have been a minimal effort (in term of refactoring and changing habits). However, we wanted to go further in our componentization approach. We discarded inline styles: they are restrictive, the trend is about dynamic style sheets, to enjoy CSS full power. We also discarded solutions which simply consist of embedding CSS in JS, and not embedding CSS in components.
We chose to highlight four libraries (non-exhaustive list):
Other libraries we didn't evaluate but we could have:
Making a choice: fela
All libraries mentioned are excellent. Our experimentation and choice making was time-boxed, and at the end we feel we made what we think is the best choice for us and our circumstances, maybe not for everyone.
They are all inline CSS libraries (and not inline styles), so they support pseudo-elements, pseudo-selectors, media queries, prefixing and value fallbacks.
They also all support server-side rendering. Support for React Native was a nice to have (styled-components, fela, glamorous). We regarded atomic CSS (styletron, fela) as an implementation detail.
Syled-components uses raw CSS, other libraries use object literals.
We weren't going to base our choice on popularity: they all have safe levels of monthly downloads and activity in their repositories.
Fela was discovered when doing our research, we hadn't heard about it before, and it won the argument for mainly two reasons: flexibility and extensibility.
- Flexible API: you can abstract away class names by wrapping elements with a styling HoC (like with styled-components, glamorous or styletron). Or you can use a styling HoC on a composite component, manually distributing class names. I view this as very important for componentisation (passing class names as props, avoiding to wrap components with elements) and for integration with 3rd party libraries.
- Extensible: fela has plugins, reminding me of postCSS plugins. It adds to fela's flexibility. Existing plugins for pseudo selectors and media queries make working with object literals much better (
:hover, etc...). It gives you power to create your own API / way of writing style objects. It also has enhancers which are basically renderer decorators. Fela uses atomic CSS which is reknown its bad developer experience. Fela offers a monolithic enhancer (with the option to include rule names) for a better DX.