The Differing Perspectives on CSS-in-JS

Avatar of Chris Coyier
Chris Coyier on

Some people outright hate the idea of CSS-in-JS. Just that name is offensive. Hard no. Styling doesn’t belong in JavaScript, it belongs in CSS, a thing that already exists and that browsers are optimized to use. Separation of concerns. Anything else is a laughable misstep, a sign of not learning from the mistakes of the past (like the <font> tag and such.)

Some people outright love the idea of CSS-in-JS. The co-location of templates and functionality, à la most JavaScript frameworks, has proven successful to them, so wrapping in styles seems like a natural fit. Vue’s single file components are an archetype here.

(Here’s a video on CSS-in-JS I did with Dustin Schau if you need a primer.)

Brent Jackson thinks you should definitely learn it, but also offers some pragmatic points on what it does and doesn’t do:

What does CSS-in-JS do?

  • Let you author CSS in JavaScript syntax
  • Colocate styles with components
  • Take advantage of native JS syntax features
  • Take advantage of anything from the JS ecosystem

What does CSS-in-JS not rid you of needing to understand:

  • How styles are applied to the DOM
  • How inheritance works
  • How CSS properties work
  • How CSS layout works

CSS-in-JS doesn’t absolve you of learning CSS. Mostly, anyway.

I’ve heard lots of pushback on CSS-in-JS in the vein of “you people are reaching for CSS-in-JS because you don’t understand CSS” or “You’re doing this because you’re afraid of the cascade. I already know how to scope CSS.” I find that stuff to be more poking across the isles that isn’t particularly helpful.

Laura buns has a wonderfully two-sided article titled “The web without the web” part of which is about React and CSS-in-JS:

I hate React because CSS-in-JS approaches by default encourage you to write completely self-contained one off components rather than trying to build a website UI up as a whole.

You don’t need to use CSS-in-JS just because you use React, but it is popular, and that’s a very interesting and fair criticism. If you scope everything, aren’t you putting yourself at higher risk of inconsistency?

I’ve been, so far, a fan of CSS modules in that it’s about as light as you get when it comes to CSS-in-JS, only handling scoping and co-location and that’s about it. I use it with Sass so we have access to mixins and variables that help consistency, but I could see how it could allow a slide into dangerous too-many-one-offs territory.

And yet, they would be disposable one-offs. Code-splittable one-offs. Everything exists in balance.

Laura goes on to say she likes CSS-in-JS approaches for some of the power and flexibility it offers:

I like the way CSS-in-JS gives you enough abstraction to still use tricks like blind owl selectors while also giving you the full power of using JS to do stuff like container queries.

Martin Hofmann created a site comparing BEM vs. Emotion that looks at one little “alert” component. I like how it’s an emotionless (literally, not referencing the library) comparison that looks at syntax. BEM has some advantages, notably, requiring no tooling and is easily sharable to any web project. But the Emotion approach is cleaner in many ways and looks easier to handle.

I’d like to see more emotionless comparisons of the technologies. Choice A does these three things well but is painful here and here, while choice B does these other things well and solves a few other pain points.

We recently linked up Scott Jehl’s post that looks into loading CSS asynchronously. Scott’s opening line:

One of the most impactful things we can do to improve page performance and resilience is to load CSS in a way that does not delay page rendering.

It’s notable that an all-in CSS-in-JS approach gets this ability naturally, as styling is bundled into JavaScript. It’s bundled at a cost. A cost to performance. But we get some of that cost back if we’re eliminating other render-blocking things. That’s interesting stuff worthy of more data, at least.

I might get my butt kicked for this, but I’m a bit less interested in conversations that try to blame CSS-in-JS for raising the barrier to entry in the industry. That’s a massive thing to consider, but we aren’t talking about shutting down CSS here and forcing everyone to some other language. We’re talking about niche libraries for certain types of projects at certain scales.

I think it’s worth taking a look at CSS-in-JS ideas if…

  • You’re working on a component-heavy JavaScript project anyway.
  • You’re already co-locating templates, functionality, and data queries.
  • You think you can leverage it without harming user experience, like gaining speed back elsewhere.
  • Your team is comfortable with the required tech, as in, you aren’t pushing away talent.

Max Stoiber is an unabashed fan. His post on the topic talks about the confidence this style brings him and the time he saves in finding what he needs, both things I’ve found to be true. But he also thinks the approach is specifically for JavaScript framework apps.

If you are using a JavaScript framework to build a web app with components, CSS-in-JS is probably a good fit. Especially if you are part of a team where everybody understands basic JavaScript.

I’d love to hear y’all thoughts on this in the comments. Have you worked out your feelings on all this? Madly in love? Seething with dislike? I’d be most interested in hearing success stories or failure stories on real projects.