I design and build simple, human and inclusive websites.
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:
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 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.
I’ve built many websites. They were never slow because we used semantic class names.
Recently I read that
.group is no more semantic than
.clearfix— I agree because neither are good class names. A badly-named class name has no bearing on the validity of the approach itself.
Atomic classes are marketed as single purpose. Semantic classes are also single purpose. They don’t normally contain one rule but they are single purpose. And…
Atomic CSS frameworks may contain several rules for each class. Makes the name misleading.
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?
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.
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.
blk mean, for example? Does it mean black or block? Let’s say it means black. Is that black text or a black background.
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.
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.
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.
I built a site recently which totals 48kb. It has many components, fussy styles and breakpoints too. Blame the visual designer for that.
Despite all 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.
CSS abstracted all the rules and permutations for us, so that we can specify what we want, when we want. Thank you CSS.
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.
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.
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 .
If the styles need to change at different breakpoints, it's harder still. For example
Consider a basket that has an empty state. Each style that is different due to the state needs its own class.
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.
If we want to use
@supports we would need a
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.
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.
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:
Also, Markdown, for example, forces us to style elements through a common ancestor (with a semantic class name).
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.
Templating and a good file structure helps, but we frequently use the inspector to find CSS. AtomicCSS makes this harder for us. We shouldn’t have to rely on file structure alone to find HTML.
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.
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.
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.
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.
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.
Here’s a typical snippet 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?
Sometimes we add conditional CSS to fix Internet Explorer bugs. We can’t target atomic class names to do this.
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 post was originally published on medium.com