I think it's no exaggeration to say that in half of all web projects, CSS ends up being an unmaintainable mess.
My projects are no exception. First, everything feels under control. However, when I come back a few months later, a small change in the stylesheet can blow up the entire design. Because of that, I started to research ways to improve CSS maintainability and even ended up publishing a list of resources on the topic.
Throughout my research, I also came to know various “schools of thought” on how you should write CSS. What I was missing, though, was a high-level overview of them. Because “CSS school of thought” would have been a rather bulky term, I’ve decided to use “CSS philosophy” for this article.
In the following I will first give an overview of the four CSS philosophies and then describe each in more detail.
An overview of CSS Philosophies
A major cornerstone towards maintainable CSS, I believe, is sticking to a CSS philosophy – a particular way of writing CSS. Throughout the last ten to fifteen years, four major CSS philosophies have emerged:
- Semantic CSS
- Component-based CSS
- Atomic CSS
- Utility-first CSS
These four “schools of thought” heavily influence a developer’s workflow.
For instance, in Atomic CSS, you hardly ever find yourself editing CSS stylesheets. Instead, you’re choosing from a predefined set of so-called utility classes and apply them directly in HTML. An example would be
<div class="m10"> to apply a 10 pixel wide margin. "Looks like inline styles on steroids”, you might think. Yes, there are similarities, but also major advantages over simple inline styles.
Anyway, I’d say it’s the least common approach. Instead, I guess you’re more familiar with Semantic CSS, which is quite the opposite. In Semantic CSS, you strive for putting all styling and layout code into stylesheets, and not into HTML. As a result, you hardly ever touch the HTML when it comes to defining its visual appearance. The only thing your markup provides is classes for CSS to hook into. Everything else about the design and layout is baked into your stylesheets.
These two philosophies represent two extremes of a spectrum, where Component-based CSS and Utility-first CSS are somewhere in between. At this point, I’d also like to mention Adam Wathan’s article CSS Utility Classes and "Separation of Concerns", which more or less discusses all four approaches from a practical point of view.
Let’s start with the "oldest" philosophy, Semantic CSS.
I believe the best way to illustrate Semantic CSS is the project CSS Zen Garden by Dave Shea. Launched 2003 but now retired, it was a contest in which participants were asked to create and submit bespoke designs for a given website.
The key aspect from a CSS architecture point of view was that designers were not allowed to touch the website’s HTML. They were forced to hook into the CSS classes provided. Looking at the results, the diversity of designs is stunning, and it’s incredible how far you can get with this approach.
This way of writing CSS follows the "separation of concerns" principle strictly. HTML is for structure, CSS for styling and layout. As a consequence, you’re forced to leverage the full power of selectors. To avoid duplication of rulesets – e.g., when you want different UI elements looking the same – you group selectors. Moreover, it is challenging to keep the DRY principle while not causing unwanted effects on other parts of the site. Overall I'd say Semantic CSS is closest to the original idea of CSS.
As a personal side note, I’m still heavily influenced by this style of writing CSS. For me, however, this approach got scratches, which is the reason for my current research.
Semantic CSS is closely tied to the idea of Semantic HTML. It was 2011 when Nicolas Gallagher (@necolas) published his widely recognized and since then often referenced article About HTML semantics and front-end architecture.
He came to conclude that you should give up a bit on the semantic side of things and make your CSS more reusable. He even argues that putting styling-concerned CSS classes into your HTML isn't necessarily un-semantic. In this regard, he disagrees with the HTML5 specification's section on classes. Other CSS philosophies go even further in terms of being un-semantic, and Gallagher's article appears to mark the eventual breakout of the “semantic HTML” dogma.
Concepts like OOCSS, BEM, and SMACSS all belong to the same category of Component-based CSS. They all appeared roughly around the same time between 2009 and 2011.
When writing component-based CSS, we strive for independent CSS modules we can reuse to style our content. The typical candidates for components are navigation, buttons, lists and this sort of stuff. Bootstrap, for example, is heavily based on components.
As a short side note, BEM is about more than just CSS. It’s a methodology for building entire front-ends. So when we're talking about BEM in a CSS context, we usually only mean the BEM naming convention.
Developed at Yahoo, Atomic CSS faced the public around 2013. Challenging CSS Best Practices, by Thierry Koblentz, is one of the major pieces describing the concept.
The core idea is to have a large set of so-called utility classes that are applied to your HTML piece by piece. As a consequence, you can quickly end up with a dozen CSS classes per HTML element. As pointed out in the introduction, the natural reaction of most developers is “Isn’t this inline styles on steroids?”.
That’s quite understandable. However, a set of utility classes is superior to inline styles. Two main advantages come to mind immediately. First, classes have much lower specificity than inline styles. In fact, CSS arms inline styles with the highest specificity, which in turn means, that you can’t override any inline rules. Second, limiting yourself to a given set of utility classes limits your design choices automatically as well. Because unlike with inline styles, you may only choose between a 10, a 20, a 30 and a 40 pixel margin class. Overall this should lead to a more consistent look and feel.
Of course, there are disadvantages as well. Looking at a portion of HTML code, that follows the Atomic CSS way of doing things, we can no longer see what it represents exactly. Sure, we are still able to distinguish a button from a list due to its content and the HTML elements in use, but would we be able to tell the difference between a "primary button" and a "danger button"? Remember, classes like
.btn-danger don't exist in this philosophy. The answer is: “No, we don't”. The remedy is to package up markup into tiny template fragments. In other words, template fragments are used to define components. If this path is taken consistently, the lost semantics can be regained.
However, imagine cutting down your personal website into tiny template fragments. Doesn’t that sound tedious? Could be, but maybe it's worth a try. Anyways, I believe that structuring a project into larger, and most of all coherent chunks is a pleasant way of working as well. This is where the utility-first approach comes into play.
As far as my research goes, Utility-first CSS is the youngest CSS philosophy.
It seems that it is mainly driven by the work of Adam Wathan with his framework Tailwind CSS. The already mentioned article CSS Utility Classes and "Separation of Concerns" describes this school of thought pretty well and puts it into perspective to the other ones.
Utility-first CSS has a lot in common with Atomic CSS. You always start by using pre-defined utility classes. The major difference to Atomic CSS is that you turn a set of utility classes into a CSS component once you spot a recurring UI pattern – a button for example. For these components, you can use all the good stuff from Component-based CSS like the BEM naming convention.
So in essence, it’s a mixture of Atomic CSS and Component-based CSS. What I like about the utility-first philosophy is that you’re not doomed to make a component out of everything. In this regard, Adam Wathan puts it quite well, when he asks how often you use a “main-navigation” CSS component. In most projects only once. For these cases, you save yourself the hassle of creating a CSS component because it won't be reused anywhere else anyway.
If I were asked today which CSS philosophy I would choose, I would pick Component-based CSS or Utility-first CSS. However, I can imagine project types where Atomic CSS and Semantic CSS are a good fit as well. The latter appears to be a natural fit for classic websites. The former, I feel, is more appropriate for web applications within which you may have a library of reusable UI widgets packaged up in template fragments.
No matter which CSS philosophy, I think it’s more important to choose one at all, to stick with it and be aware of its strengths and weaknesses.