There’s always a standard of separating styling from markup since the inception of web development. HTML presentation tags were deprecated in favor of CSS files to completely separate from HTML document. And everyone has been happy with that, CSS styling is very mature with standards and techniques.
Using external CSS stylesheets has obvious benefit when you can update the styles across a whole website by updating a single document and we’re all hooked with that.
React came in town and changed everything! CSS-in-JS was born and loved by community (me too!). It’s moving in the opposite direction of style portability. What were the reasons behind it and should you adopt it? Let’s take a look at two sides of the rising star!
CSS at scale has some problems like dependencies, dead code elimination, minification, sharing constants, non-deterministic resolution and isolation.
CSS uses a global namespace for CSS selectors that can easily result in style conflicts throughout your application when building an application using modern web components. You can avoid this problem by nesting CSS selectors or use a styling convention like BEM but this becomes complicated quickly and won’t scale.
CSS-in-JS avoids these problems entirely by generating unique class names when styles are converted to CSS. This allows you to think about styles on a component level with out worrying about styles defined elsewhere.
CSS-in-JS is a delicate and controversial topic, you should approach it with an open mind.
CSS-in-JS was born to abstract away many complicated CSS concepts like cascading, specificity, naming selectors, enforcing naming conventions, enforcing file structures, preprocessors.
- Everything is component: Your styles only affect the component they’re applied to. This means you can customize your component’s CSS without worrying about how it will impact the rest of your application. Seamlessly add and remove components without constantly ballooning stylesheet size and complexity.
- Maintainable at scale: With the scoping of CSS-in-JS, teams can organize their styles in isolation without affecting one another. Stop worrying about mandated conventions and remove the need for application-wide selector hierarchies and naming schemes altogether.
- Intuitive and automated: Many CSS-in-JS libraries generate unique class names which can help with caching, automatic vendor prefixes, timely loading of critical CSS, dead code elimination, and implementing many other features, depending on the library you choose.
- React Native compatible: Some libraries support RN, I’ve been using styled-components in my RN projects and you don’t know how grateful I am.
Nothing is perfect and so is CSS-in-JS. It has some drawbacks which might shy you away from adopting it in your company.
- Unreadable class names: Most CSS-in-JS libraries generate random unreadable class names which might be a problem if you need meaningful names for other purposes like debugging or crawling.
- Performance: Might be a problem in early days, but now libraries automatically handle critical css and compiling very well means their performance is very close to normal stylesheets.
There are many CSS-in-JS techniques out there with different quality, you can try any of them for fun but definitely should only use popular ones for production. Following libraries are well developed and maintained by community:
- css-modules: An approach that tries to fix global scope of CSS by let you use the same CSS class name in different files without worrying about naming clashes, made possible by webpack’s css-loader or postcss-loader.
- styled-components: By far this library is the best and most loved solution with more than 25k stars on GitHub. I’ve been using it for 2 years and the experience is more than satisfied. Its ecosystem is getting bigger, you simply just can’t stop using it.
- emotion: The second best solution with 9k stars. This one focuses on performance and flexibility; It allows you to style apps quickly with string or object styles.
- radium: A set of tools to manage inline styles on React elements. It gives you powerful styling capabilities without CSS.
- aphrodite: A framework-agnostic CSS-in-JS library with support for server-side rendering, browser prefixing, and minimum CSS generation.
- glamor: A small, fast, efficient, framework independent CSS-in-JS library. It lets you write inline CSS in your components using the same Object CSS syntax React supports for the style prop.
Check out all css-in-js libraries here.
The CSS-in-JS technique is till very young compared to 10+ years history of CSS, but it is evolving very fast in recent years. You should give it a try on side projects using JS frameworks, especially styled-components, I bet you’ll love it the moment you touch it.
If you think the pros outweighs the cons, then give CSS-in-JS a shot!