Adam Wathan wrote an article recently called CSS Utility Classes and “Separation of Concerns”. In it, he documents his journey through different ways of thinking about CSS. A lot of it is really familiar.
Phase 1: “Semantic” CSS
Ah, yes! If you’ve been in the game for a while then this will be familiar to you. The days when we used to strive to keep our class names to a minimum and use names that described the content. But, as Adam points out:
My markup wasn’t concerned with styling decisions, but my CSS was very concerned with my markup structure.
Phase 2: Decoupling styles from structure
This is the work pioneered by Nicole with OOCSS, and followed later by methodologies like BEM and SMACSS.
This felt like a huge improvement to me. My markup was still “semantic” and didn’t contain any styling decisions, and now my CSS felt decoupled from my markup structure, with the added bonus of avoiding unnecessary selector specificity.
But then Adam talks about the issues when you have two visually similar components that are semantically very different. He shows a few possible solutions and asks this excellent question:
For the project you’re working on, what would be more valuable: restyleable HTML, or reusable CSS?
For many projects reusable CSS is the goal. But not all projects. On the Code For America project, the HTML needed to be as clean as possible, even if that meant more brittle CSS.
Phase 3: Content-agnostic CSS components
Naming things is hard:
The more a component does, or the more specific a component is, the harder it is to reuse.
Adam offers some good advice on naming things for maximum reusability. It’s all good stuff, and this would be the point at which I would stop. At this point there’s a nice balance between reusability, readability, and semantic meaning.
But Adam goes further…
Phase 4: Content-agnostic components + utility classes
Okay. The occasional utility class (for alignment and clearing) can be very handy. This is definitely the point to stop though, right?
Phase 5: Utility-first CSS
Oh God, no!
Once this clicked for me, it wasn’t long before I had built out a whole suite of utility classes for common visual tweaks I needed, things like:
- Text sizes, colors, and weights
- Border colors, widths, and positions
- Background colors
- Flexbox utilities
- Padding and margin helpers
If one drink feels good, then ten drinks must be better, right?
At this point there is no benefit to even having an external stylesheet. You may as well use inline styles. Ah, but Adam has anticipated this and counters with this difference between inline styles and having utility classes for everything:
You can’t just pick any value want; you have to choose from a curated list.
Right. But that isn’t a technical solution, it’s a cultural one. You could just as easily have a curated list of allowed inline style properties and values. If you are in an environment where people won’t simply create a new utility class every time they want to style something, then you are also in an environment where people won’t create new inline style combinations every time they want to style something.
I think Adam has hit on something important here, but it’s not about utility classes. His suggestion of “utility-first CSS” will only work if the vocabulary is strictly adhered to. For that to work, everyone touching the code needs to understand the system and respect the boundaries of it. That understanding and respect is far, far more important than any particular way of structuring HTML and CSS. No technical solution can replace that sort of agreement …not even slapping
!important on every declaration to make them
I very much appreciate the efforts that people have put into coming up with great naming systems and methodologies, even the ones I don’t necessarily agree with. They’re all aiming to make that overlap of HTML and CSS less painful. But the really hard problem is where people overlap.
The older I get, the more every problem in tech seems to be a matter of getting humans to work together effectively, and not tech itself.— Laurie Voss (@seldo) August 23, 2017