CSS in JS is Stupid

This is an informal, not polished and longer reply to a tweet of a former co-worker who stated that “CSS in JS is Stupid”.

As I see it, CSS in JS doesn’t do anything I wouldn’t do in any other language nowadays. JavaScript only happens to be the language of choice of the people who promote it.

The goal is not to talk about technologies anymore (HTML, CSS and JS) but things i.e. components and in this case coupling your JS to your Styles is necessary.

Disclaimer: if you are living in the universal JavaScript bubble probably this post is a waste of time and you should just yarn add any of the CSS in JS libs out there.

When we talk about CSS in JS the “in JS” part is just an implementation detail and commodity.

Assuming that we all aim to write modular, component-based code and want to write static only CSS, JavaScript per-se is not a requirement at all.

Scoped styles can be written in plain CSS Modules and, with the help of an adapter, any language or templating system can consume them.

in many cases it completely breaks the cascade

Cascade is a very powerful CSS feature but, as always, with great powers come big responsibilities.

My opinion here is that when we don’t have control over the cascade, like we do in ShadowDOM, it is better to keep it out of the equation.

Each element (HTML tag) should be affected only by one ruleset and selectors should all have the same specificity.

If we are a disciplinate mass of engineers who uses one CSS class per HTML tag and we don’t have state :hover, :focus, .is-open etc then we shouldn’t have any big issue.

If that’s not the case instead, then we have to deal with non deterministic resolution and cascade – this might be an issue with some CSS in JS implementations too e.g. CSS Modules (the JavaScript implementation).

Finally many confuse Cascade with Inheritance.

Inheritance is about inherited properties (surprise) like color, font etc. Those are not reset or controlled in most of the CSS in JS libraries or even ShadowDOM.

sounds like something good conventions and a linter could easily solve

This is a common remark. In reality it’s never worked that well at the company we both work[ed] for or at any other job really :)

Why fighting to enforce a convention or good practice when we can get that from a tool and out of the box? No exceptions, hacks, lazy day etc.

We can get this to work in Python, Ruby, PHP or any other language really.

CSS Modules for example, produce maps of { actual: scoped } class names (strings). Basically a dictionary that we can import in our templates and use to reference the unique, scoped classes which are generated at build time by a tool.

it requires a (typically complex and slow) build system

What doesn’t nowadays? SASS requires a build system too. In fact I remember that at some point we started to contribute to its C/C++ compiler to be able to switch to that and improve our build time.

Some CSS in JS libraries like emotion don’t even require a build step and are very perfomant.

Anyway, with such a modular system Server Side Rendering is straightforward and with very little work we can also get critical CSS extraction by creating a list of modules for each view and dumping link tags on the page.

Technically we could even create bundles out of those lists and deliver only a file with the amount of CSS needed for a page to look as expected.

Yes, there will be repetition and somebody will create a common bundle. This bundle is cached and shared across pages and each single page has to load the remaining styles.

Moving on, our page is SSR-ed and we are on the client now. The first real issue to deal with is doing progressive enhancement on the client without loading all the CSS ahead of time.

Modules can use a little helper to load/unload/dedupe additional CSS bundles depending on the state of the JavaScript component.

One way or another we need some sort of CSS StyleSheets Manager and, since we are on the browser, we cannot use anything but JavaScript to implement this.

For the most part this is what CSS in JS does, and what I would do today if I were to build an application or website with another language.

it couples your JS to your styles

Just like JSX, CSS in JS is about using the language of choice to enhance the authoring experience and define an easier way to interoperate.

The goal is not to talk about technologies anymore (HTML, CSS and JS) but things i.e. components. In this case coupling is necessary.

JavaScript only happens to be the language of choice in a specific application or website.

A non-js example of this is Cheetah – a template engine for Python. It couples HTML with Python for the good.

The good thing about using JavaScript to author CSS is that we have an actual programming language to do things like loops, variables, composition. We don’t have to rescue to underpowered quasi-programming languages (preprocessors) to do so.

The author of Mustache.js did a great job at explaining why this is a great idea. You may want to watch his talk:

👋