Automated CSS Atomization, shrinking CSS files by 80%
Tags: webdev, tooling, optimization, atomizatio
Published: 2023-01-24 16:37:07

There is a little known optimization technique that I've been interested in for the past few years (more on that later). The promise it offers is quite substantial. The ability to reduce the amount of CSS you ship by 60-80% (for the average site/app). Though the cost today, in level of effort, maintenance, and complexity is too high for the average project to justify. So the technique is relegated only to the likes of Google, Facebook, and Twitter.

The approach this article will explain is called **"Automated CSS Atomization"**. That's some fancy sounding jargon, *but what does it mean*? Essentially, it is a process where a tool evaluates your CSS for patterns and repetition, and then restructures it in a more efficient manner resulting in the same visual outcome on the page, but requiring dramatically less code to reproduce that effect. It is a build step.

For a real-world case study, when converting the *Facebook.com* homepage to use automated CSS atomization, they found it [reduced their homepage CSS by **80%**](https://engineering.fb.com/web/facebook-redesign). The performance gains you get from this approach are all highly dependent on the codebase, but Facebook's results aren't considered outliers, most projects save around 60%-80%. If you are already "pre-atomizing" your code, with a tool like Tailwind, then expect to see savings closer to 10-20%. Or if you heavily use `@apply` in your Tailwind projects, you may see benefits closer 50-70%.

> *A short aside on atomic CSS libraries:*
>
> If you are familiar with any Atomic CSS libraries, such as "Tailwind", they attempt to give you the same benefit I'm talking about in this article, however, they require you to do the atomization part by hand. Logically, computers are better at being compilers than humans, and humans are better at assigning context and meaning than computers are. So systems like Tailwind, though popular, are somewhat backwards to what one would expect, and doesn't really play to the strengths of either humans or machines. This isn't an indictment of Tailwind (*or any other atomic CSS library, like Tachyons, ACSS, FunCSSion, etc*). Tailwind specifically offers a lot more value than just performance. It isn't even it's primary goal. Humans just aren't ever going to be able to perfectly optimize their code by hand every time.
>
> The real beauty of using a tool to automate the atomization process is that you can write your CSS using *any programing style, any methodology, any paradigm, and any tooling you want*. The result will always be a consistent, and smalller, representation of the code.

So lets dive in to an, admittedly, over-simplified example to convey what this automated process really does.


## Intro to CSS Atomization

CSS Atomization is an optimization technique where you take in any CSS stylesheet:

```css
.headline {
  padding: 1rem;
  margin: 2rem;
  font-size: 2em;
}
.side-nav {
  padding: 1rem;
  margin: 2rem;
}
```

Examine each CSS rule in the style sheet:

```css
.headline {
  padding: 1rem;
  margin: 2rem;
  font-size: 2em;
}
```

Then create new atomized classes based on the property/value pairs:

```css
.padding-1rem { padding: 1rem }
.margin-2rem { margin: 2rem }
.font-size-2em { font-size: 2em }
```

And associate the original class names to the new atomized classes:

```js
{
  'headline': 'padding-1rem margin-2rem font-size-2em',
  'side-nav': 'padding-1rem margin-2rem'
}
```

This map of classes is then used to update any markup you have, so this:

```html
<h1 class="headline">Example</h1>
<nav class="side-nav">Example</nav>
```

automatically becomes this:

```html
<h1 class="padding-1rem margin-2rem font-size-2em">Example</h1>
<nav class="padding-1rem margin-2rem">Example</nav>
```

Because this is a build step, and the output doesn't need to be human readable, this process can even automatically shrink the class names for you.

```css
.a { padding: 1rem }
.b { margin: 2rem }
.c { font-size: 2em }
```
```js
{
  'headline': 'a b c',
  'side-nav': 'a b'
}
```
```html
<h1 class="a b c">Example</h1>
<nav class="a b">Example</nav>
```

And the generated classmap can be used in your JavaScript.

**Vue.js example:**

```html
<h1 :class="s.headline">Example</h1>
<nav :class="s['side-nav']">Example</nav>
```

**Svelte example:**

```html
<script>
import s from '../classMap.js';
</script>

<h1 class={s.headline}>Example</h1>
<nav class={s['side-nav']}>Example</nav>
```

**JSX example:**

```jsx
import s from '../classMap.js';
export function AnExample () {
  return (
    <div>
      <h1 className={s.headline}>Example</h1>
      <nav className={s['side-nav']}>Example</nav>
    </div>
  );
};
```

Having to reference a class map in your JavaScript is the most manual step in the process. But even it is a pretty small level of effort. Especially compared to a lot of other CSS techniques commonly employed today.


## If the big tech companies are doing it, why isn't everyone else?

As I mentioned in the opening, currently the process is quite cumbersome. Today, there is no easy way to automate CSS atomization. It's possible, but only by combining dozens of libraries that aren't specifically designed to interconnect to solve this problem. So you end up with a lot of finicky "glue" code, a lot of dependencies to manage, and ultimately you'll need deeper technical knowledge of what kinds of CSS you can and can't write, as not everything will work with these systems.


## A brighter future

The potential of this technique is huge. If a tool was created that lowered the barrier of entry, then widespread adoption could be achieved. Just take a moment to imagine a future where that happens. A future where atomization becomes as common practice as minification or uglification. That would mean most of the CSS added to the internet from then on would be 60-80% smaller. That leads to, across the entire internet, smaller files, faster page loads, lower CPU usage, lower battery usage. This would have a *measurable* impact on global carbon emissions.

But alas, that easy to use tool doesn't exist. At least... not yet...

I've started an open source project to solve this problem.

**It's called [Red Perfume](https://red-perfume.github.io).**

Red-Perfume's goal is to simplify this process so that anyone can easily add atomization to their projects. As part of this approach, the entire atomization process is handled by this library, so that all features are added and all bugs are fixed in one place, resulting in a more optimized tool. The API is designed to be super easy, but fully extendible for any pipeline. And we are aiming to support any arbitrary CSS file.

At time of writing, Red-Perfume is still experimental and a work in progress, so simple CSS works fine, but more advanced CSS isn't supported yet. But we're [working hard to support all of the CSS spec](https://github.com/orgs/red-perfume/projects/2). If you're interested in contributing to the project, it's all open source and on GitHub, and we could use the help from skilled developers.

Learn more about Red Perfume on it's website:

* https://red-perfume.github.io

* * *

*Photo from [@LEGO_Group](https://twitter.com/LEGO_Group/status/1485617151604109317/photo/1)*