CSS-in-JS Sucks: a romantic rant


What is CSS-in-JS?

CSS-in-JS is the generic name for a group of really powerful developer tools that allow us to code a product’s styles in Javascript.

In the olden days, people used to inject CSS into html via Javascript, which created inline CSS on the element it was working on.

We all know inline CSS is evil. Even the people making CSS-in-JS tools know that it’s evil. That’s not what this is.

CSS-in-JS lets developers coding in React to code CSS so that it matches React’s component-based development practice. It creates its own stylesheets that are included in the DOM exactly the way we normally would for regular ol’ CSS.

You can even use it to define critical CSS styles that sit in a style tag within the DOM’s head. It’s pretty amazing.

So, why do you hate it so much, Josh?

So, did I waste your time with some ridiculous link-baity title that Esther came up with and I agreed to?

No. I didn’t. CSS-in-JS fills me with a fear for the sustainability of our web products. I think we use the speed and convenience of being able to code things quickly that we know will scale as products scale to save our customers money now even though they are going to pay more for it down the track.

html & css & js

The way the web renders is a thing of beauty. I really love it. It’s come so far and CSS is what prompted me to start learning to code websites. I understood it implicitly. When I started working with a bunch of Java developers, I could troubleshoot their CSS in seconds. When Ethan Marcotte developed responsive CSS practices, I shouted from the rooftops and changed the way I did everything. Now that the CSS grid spec is being adopted, I’m over the moon about the things we can do with it.

Built into the web, into this wonderful triumvirate of markup and script that gives us cat memes, infinite Medium articles about the same topic, and a hundred different ways to say we liked someone’s photo, is this idea that we can make changes to any one of these pieces and maintain the fidelity of the others. The backbone of the web is modular, in this way.

Nothing made this more clear to me than CSS Zen Garden. It’s a beautiful website that allows anyone to take an existing and standard piece of html and code their own CSS for it, and then share it with the world.

It revealed to me the beauty and simplicity of great web development:

1. html

Everything starts with planned html. Naming is important. Understanding inline vs block elements is important. Understanding the difference between semantic and non-semantic elements is important. These things are important because so many technologies rely on them being the way they were designed. Good html forces us to understand the content that we’re coding for.

  • Is something a button or is it a link?
  • What is the hierarchy of information we want to mansplain?
  • What kind of list is that? Oh, it has terms and then definitions for those terms? Well, it’s a definition list which is totally a thing that most people don’t know exists.

The way html was designed should force us to think about what it is we’re putting on the page. Without either of html’s other webdev buddies, a well-constructed site will still work. It might be ugly and require a lot more scrolling than we wanted, but it will still make sense and the interactions will still work.

2. html + CSS

Then we add CSS to it. For all the beauty in html’s design, it’s a giant oaf compared to the finesse CSS brings to it.

CSS is not just about making things look more visually appealing. That’s part of it. But in reality it’s a deeper dive into the meaning of what we’re creating. This is where selectors, IDs, classes, attributes, pseudo classes and combinators come in. They get us to understand and better display the meaning of what we’re producing by forcing us to make more difficult decisions.

Using CSS, we can make use of the different physical tools people use to interact with what we’ve built. We can create subtleties and nuance and add emotion to something that previously was just words and pictures.

We’re forced to think about how and why something looks and reacts the way it does. We can create emotional responses in our users.

But, in order to do this, we need to really think about what it is that we’re putting on the screen. We need to think about how the html is constructed and what responses we want to elicit from our user. One of the ways we do this is through CSS’s greatest power: the cascade.

The cascade runs through importance, specificity and source order to give us better control over how something will display, but also to give us constraints that tie very closely in with the html, so that what we’re displaying matches the original intention of the page.

This is why class names are so important. Good, semantic class names in the html give us clues about the intention of the page we’re presenting. That intention won’t be fulfilled by the big, clumsy baby that is html. It can only truly be made true by the CSS we produce for it.

As CSS Zen Garden showed us, a single, well-constructed html document can be given all sorts of nuanced meaning through the CSS we attach to it. This nuance should be able to evolve over time as we learn new things about how the users are interacting with our product. We should be able to tweak the stylesheets over time or create new stylesheets for new media that becomes important, by just writing some new CSS. We can create stylesheets specifically for printing so that we can make the digital analogue (although almost nobody does and almost all websites look terrible when printed).

This is why CSS-in-JS bothers me so much. What we gain in speed of development, we lose in sustainability and adaptability. CSS-in-JS is an abstraction from the very nature of the thing we’re producing. It takes away the burden of having to think about the screen and the devices that might interact with it. It removes the value of the cascade by hacking the specificity so that we don’t have to think about it.

By doing that, it removes us, our very selves, further away from the intention of our product. It denies us the privilege of designing the front-end experience at its very DNA.

3. html + css + js

Javascript is an immensely powerful tool. React is an amazing framework that makes coding web applications so much easier. All the different CSS-in-JS tools help us code web applications so much faster. So many articles I read in trying to articulate my argument talk about the reduction of cognitive load that comes with CSS-in-JS. But with that convenience comes a cost that we might not see straight away.

When a client goes through a rebrand, they shouldn’t have to rebuild all of their web assets. When a new technology comes along, future developers shouldn’t have to deal with inherited tech-debt just to make something work.

The web and the specs that define it, give us the perfect opportunity to combine research, design and development, to work in parallel in true agile teams, building with a true lean production ethos. CSS-in-JS strips us of that and leaves us in the old waterfall approach of designers handing over comps to developers, who then just make it work on the screen.

I think we’re better than that.


Some Reading