The problem with atomic CSS

Since publishing MaintainableCSS I’ve received some criticism from advocates of atomic CSS. One person said they puked up all over their screen after reading it, which was mildly entertaining.

When I wrote about semantic class names, it made sense to talk about them in comparison to non semantic class names. Often we deduce what it is we should do, once we analyse what it is we shouldn’t.

In response, atomic CSS champions critiqued semantic CSS. I actually don’t mind the critique. It’s good to be challenged. It certainly challenged my own thinking, but so far, my mind is unchanged.

In this article, I’m going to explain fully why that is. And I’ll also address some of the comments made by atomic CSS advocates. Here goes:

1. “Semantic is a misleading word”

In Understanding Semantics, Léonie Watson points out that semantic means of code intended to reflect structure and meaning.

This is why the word wrapper is semantic. It is an element that wraps another, always. Whether CSS clears floated “columns” on big screens or stacks them on small screens, it’s always a wrapper.

Therefore once we write HTML, it doesn’t need to change. Where as a class of red, or clearfix is not semantic — at least in the context of HTML.

In the context of HTML, a semantic class name describes what it is, not what it looks like (or how it behaves). This compliments the element itself. The element describes what it is, not what it looks like.

2. “Semantic classes result in slow sites”

I’ve built many websites. They were never slow because we used semantic class names. For example, I built a responsive e-commerce site in 2016 which totals 48kb.

It has many components, fussy styles and breakpoints too. (Blame the visual designer for that. :D )

Despite this, the CSS isn’t slow. And it’s not like I paid much attention to CSS performance. No doubt we could make savings. But no bother, it’s not hurting users at all.

3. “Atomic CSS ensures design is consistent”

The theory is, that if I’m only allowed to use predefined classes, the visual design is more likely to stay consistent.

This makes some sense, because it limits the developer to what styles they can use. At least in theory.

However, it’s all in the application. There is nothing to stop me adding, for example, a new margin-bottom class or using the wrong one.

Perhaps there is an opportunity to create a tool as opposed to a convention to solve this?

4. Analysing CSS performance in isolation

The most touted aspect of atomic CSS is size and performance — in particular, time to first paint. Advocates often discuss this in isolation, which at best is misleading and at worst it’s deceiving.

Firstly, the size of the HTML increases significantly. Remember, CSS is cacheable and often serves an entire website. HTML is often unique, dynamic and personalised. It can’t be cached.

Secondly, the amount of CSS saved — even on large sites — would be relatively small. I am sure there are stories of websites with ten trigabytes of CSS, but having built many websites, I’ve found CSS is rarely the culprit.

Moreover, the size of CSS is not the only performance indicator. There are many others and they need to be thought about holistically.

5. Atomic classes are hard to read

Atomic class names are typically abbreviated. Abbreviations are hard to read. They have to be understood and mentally mapped. We should strive for clarity over brevity.

What does blk mean, for example? Does it mean black or block? Let’s say it means black. Is that black text or a black background.

(Whilst this is not something I’ve made up, it’s important to note that a badly named atomic class name has no bearing on the validity of the approach.)

We can use verbose names that are easier to read, but then this exacerbates the problem of HTML bloat and performance — which is the reason for abbreviations in the first place.

Or perhaps it’s about saving keystrokes, but any decent editor will have autocomplete.

6. Atomic CSS recreates CSS in HTML

Atomic CSS recreates the same constructs found in CSS in order to use classes in HTML. CSS was designed for styling. It’s tedious having to recreate a convention for HTML, that encourages developers to use the wrong tool for the job.

7. We need semantic hooks anyway

In order to write functional tests and enhance websites we’re going to need semantic classes. Therefore there is going to be a mix of classes each reserved for different things.

Inconsistent code is hard to reason about and if there are two ways of doing something, inevitably they will be misused.

8. Semantic CSS doesn’t violate DRY

Trying to reuse a CSS rule, is like trying to reuse a variable across different Javascript objects. It’s simply not in violation.

CSS abstracted all the rules and permutations for us, so that we can specify what we want, when we want. Thank you CSS.

9. Semantic CSS is easy to delete

A semantically-defined component is easy to delete because the related CSS pertains to that module in question. Atomic CSS is intertwined across a multitude of elements making the code hard to delete.

Before deleting the related CSS you would first need to look at each class, on every element within the module, to determine if it is used elsewhere. Only then can you decide whether to delete it or not.

Good code is easy to delete because it’s not intertwined.

10. Atomic CSS is a responsive design anti-pattern

As Ben Frain states in Atomic CSS is a Responsive Design Anti Pattern, making very specific changes at certain breakpoints and tying them to a class that has to be added to the HTML seems needlessly complex.

He continues to say that you inevitably end up with a raft of classes in your stylesheets that are obsolete.

11. It’s harder to style pseudo classes

For every single style you want changed, you need an equivalent, verbose and hard-to-read class name. For example .red-text-when-hover and .black-bg-when-focus etc.

If the styles need to change at different breakpoints, it's harder still. For example .red-text-when-hover-on-large-screens.

12. It’s harder to style based on state

Consider a basket that has an empty state. Each style that is different due to the state needs its own class.

13. Javascript now needs to manage styles too

Let’s say we have the following HTML:

<div class=”red-text float-left border-1px border-color-red”>

Now, in response to some state, Javascript needs to change the module to have 2px borders that are blue. You need to add (and optionally remove) individual styles from within the Javascript component. Meaning that Javascript has to be “style aware” too.

14. It’s harder to style based on reading direction

David Mark’s tweet covers this:

…invariably, “pull-left” contains float:right in RTL configurations. That’s a clue as to why it makes no sense.

15. It’s harder to enhance

If we want to use @supports we would need a .supports-x-do-y-class-name.

16. It’s harder to change layout mechanisms

As Ben Frain says in the same article, suppose […] we change our product […] from float based layouts to Flexbox based layouts. We now have twice the maintenance burden.

17. It’s harder to fix Internet Explorer issues

Sometimes we add conditional CSS to fix Internet Explorer bugs. We can’t target atomic class names to do this.

18. Atomic classes are misleading and redundant

For example, overflow-hidden is used to clear floated children. However, in small screens the children are stacked, not floated. This is misleading for developers and redundant for users.

19. Every element needs classes

With atomic CSS every element needs several classes. But sometimes we don’t need to add a hook, as we can do this: .blah div or this:input[type=submit].

Also, Markdown, for example, forces us to style elements through a common ancestor (with a semantic class name).

20. It makes the inspector noisy

It’s hard to determine where a module starts and ends as there is nothing in the HTML to indicate this. The content is obfuscated and the inspector has more lines of code to look through.

Many declarations is a cognitive burden on developers

21. It’s hard to find HTML

We often inspect elements using the inspector. Atomic classes aren’t unique, meaning it’s hard to use those hooks to find out where the HTML lives. Good file structure and templating helps, but we shouldn’t have to solely rely on it.

Using Atomic hooks to find HTML is not going to yield positive results

22. “Switching between HTML and CSS is hard”

Some commend atomic CSS because there is less switching between CSS and HTML.

Of all the things developers have to do, pressing cmd+tab is hardly taxing.

Moreover, it’s practically nonsense. The only way you won’t have to switch to CSS is if you know every available class name at your disposal. I doubt this is the case for most people.

23. “Atomic CSS makes it easy to reuse CSS across projects”

Advocates suggest atomic CSS makes it easy to reuse CSS across projects. It’s a nice idea, but it’s practically useless unless every site is going to look the same. Most websites don’t.

24. It’s hard to theme CSS

When I worked on a white-label solution for several e-commerce sites, the HTML was reused, not the CSS. That’s because the HTML is similar, not the CSS.

25. It’s hard to create new components

On your first day at a new job, you have to develop a new component.

Instead of giving the component a semantic class and styling it, you have to add a multitude of classes that you’ve first checked exist or not. You can’t simply know what class names are available. Therefore the job is harder.

26. It’s hard to edit an existing component

This time you need to change a component. You manage to find the HTML but this time you have to work out which classes need removing and adding.

To add one, you must first check the existence of a class before you may or may not use it. If it’s there, you can use it. If it’s not, create one.

I don’t know anyone that reads all the available CSS to see if there is something they can reuse.

27. “Semantic classes are longer than atomic class names”

Here’s a typical snippet of atomic CSS from a site that has basic styling:

class="w5 w6-m w-50-l center overflow-visible mt3 mt4-m dtc-l v-mid-l tr-l"

I’ve never seen a semantic class name that is close to this. Have you?

Summary

In many cases, atomic CSS will decrease the size of your CSS file. That’s to be expected. Just like if decided to inline all my styles, I would expect the size of the CSS file to be zero bytes.

The problem is that it introduces many other issues that we would be foolish to ignore.

Performance is only an issue once it becomes an issue. There could be many factors at play.

I’m not saying to wait for a problem, but I’m not saying we should discard tried, tested and technology-embracing techniques like semantic CSS either.

There are other ways of making websites load faster with regards to CSS. For example, we don’t have to load the entire site’s CSS at once. We could include the CSS a page needs and cache progressively.

Focussing on CSS isn’t necessarily where our energy is best spent. Perhaps the page has too much stuff. Perhaps the visual design is wasteful and not benefiting users. You might be using a framework, CSS or otherwise which you don’t need.

All in all, having to navigate our way through all the trade-offs to shave some CSS, which drastically increases the size of HTML, is just trading one problem for several others.

In most cases, we’re going to need semantic classes to do the job regardless. We may as well make use of them for CSS too.

This is something I first wrote to my subscribers. I send an email out like this once a month ish. If you want to avoid all my past mistakes, sign up here.