On Auto-Generated Atomic CSS

Avatar of Chris Coyier
Chris Coyier on (Updated on )

Robin Weser’s “The Shorthand-Longhand Problem in Atomic CSS” in an interesting journey through a tricky problem. The point is that when you take on the job of converting something HTML and CSS-like into actual HTML and CSS, there are edge cases that you’ll have to program yourself out of, if you even can at all. In this case, Fela (which we just mentioned), turns CSS into “atomic” classes, but when you mix together shorthand and longhand, the resulting classes, mixed with the cascade, can cause mistakes.

I think this whole idea of CSS-in-JS that produces Atomic CSS is pretty interesting, so let’s take a quick step back and look at that.

Atomic CSS means one class = one job

Like this:

.mb-8 {
  margin-bottom: 2rem;
}

Now imagine, like, thousands of those that are available to use and can do just about anything CSS can do.

Why would you do that?

Here’s some reasons:

  • If you go all-in on that idea, it means that you’ll ship less CSS because there are no property/value pairs that are repeated, and there are are no made-up-for-authoring-reasons class names. I would guess an all-atomic stylesheet (trimmed for usage, which we’ll get to) is a quarter the size of a hand-authored stylesheet, or smaller. Shipping less CSS is significant because CSS is a blocking resource.
  • You get to avoid naming things.
  • You get some degree of design consistency “for free” if you limit the available classes.
  • Some people just prefer it and say it makes them faster.

How do you get Atomic CSS?

There is nothing stopping you from just doing it yourself. That’s what GitHub did with Primer and Facebook did in FB5 (not that you should do what mega corporations do!). They decided on a bunch of utility styles and shipped it (to themselves, largely) as a package.

Perhaps the originator of the whole idea was Tachyons, which is a just a big ol’ opinionated pile of classes you can grab as use as-is.

But for the most part…

Tailwind is the big player.

Tailwind has a bunch of nice defaults, but it does some very smart things beyond being a collection of atomic styles:

  • It’s configurable. You tell it what you want all those classes to do.
  • It encourages you to “purge” the unused classes. You really need to get this part right, as you aren’t really getting the benefit of Atomic CSS if you don’t.
  • It’s got a UI library so you can get moving right away.

Wait weren’t we talking about automatically-generated Atomic CSS?

Oh right.

It’s worth mentioning that Yahoo was also an early player here. Their big idea is that you’d essentially use functions as class names (e.g. class="P(20px)") and that would be processed into a class (both in the HTML and CSS) during a build step. I’m not sure how popular that got really, but you can see how it’s not terribly dissimilar to Tailwind + PurgeCSS.

These days, you don’t have to write Atomic CSS to get Atomic CSS. From Robin’s article:

It allows us to write our styles in a familiar “monolithic” way, but get Atomic CSS out. This increases reusability and decreases the final CSS bundle size. Each property-value pair is only rendered once, namely on its first occurence. From there on, every time we use that specific pair again, we can reuse the same class name from a cache. Some libraries that do that are:

Fela
Styletron
React Native Web
Otion
StyleSheet

In my honest opinion, I think that this is the only reasonable way to actually use Atomic CSS as it does not impact the developer experience when writing styles. I would not recommend to write Atomic CSS by hand.

Johan Holmerin wrote about style9 here on CSS-Tricks too which does the same.

I think that’s neat. I’ve tried writing Atomic CSS directly a number of times and I just don’t like it. Who knows why. I’ve learned lots of new things in my life, and this one just doesn’t click with me. But I definitely like the idea of computers doing whatever they have to do to boost web performance in production. If a build step turns my authored CSS into Atomic CSS… hey that’s cool. There are five libraries above that do it, so the concept certainly has legs.

It makes sense that the approaches are based on CSS-in-JS, as they absolutely need to process both the markup and the CSS — so that’s the context that makes the most sense.

What do y’all think?