I am in the habit of using an esoteric system for CSS. This posts documents it so I have a reference in the future and so I look like less of a crazy person to anyone browsing my CSS.
The idea isn't my own, a colleague introduced me to it several years ago, to my knowledge he's never bothered to write up his ideas. I realize there exist tools to accommodate these problems but heavy-handed tooling has never jibed with me. I've tried to keep up with recent trends in the CSS ecosystem including BEM and SASS to identify the useful parts which I might incorporate into my current practices.
The big picture is simply "globally unique class-level selectors only". Which
means rather than using top-level selectors like div
and a
or ID selectors
like #app
I use .btn-99f70
and .app-container-5283a
. I realize how weird
this looks.
By using a random 5 character hex string on each class you guarantee uniqueness. The 5 character limit is enough to guard against collisions while still being memorable and largely unobtrusive (to my eye). The number of possible permutations for 5 characters of the hex range (16 characters) can be expressed as:
165 = 1,048,576
Meaning the chances are vanishingly small that you might name two buttons or links the same.
Using only class-level selectors results in levels of specificity which may be combined in a predictable manner. This is not a unique idea, it is present to some degree in:
OOCSS: Probably most similar to this system, but lacks the uniqueness
guarantees and allows for specificity conflicts. Which .header-nav
takes
precedence, how can you (quickly) find out?
BEM:What I am describing is in
the spirit of BEM but much less rigid, I think. BEM aims to describe your
markup which, while possible, isn't required with this system. You might
have a div widget-container-879d4
, but it is entirely on you to, well,
contain elements within it.
I've been reading recently about how some companies "do CSS" and was interested to see that it isn't a solved problem for some of the big names. For instance, reading about GitHub's CSS:
The order in which styles get applied matters. It really shouldn't, but in every design system there are rules and a basic hierarchy of styling. With the Sprockets approach, we sometimes run into specificity problems. This happens because new files can be added to either bundle at any time. Depending on their file name, they appear in different spots in the compiled CSS.
Also, regarding how they manage stale classes:
Running a script that greps for a class in our CSS to see if it exists in our views. (We've recently made this part of our CI tests, so we constantly see it now.)
It so happens that with unique class level selectors this is a trivial operation
and can be combined with diff
to check a whole project. I use
ag to do this, but grep
or ack
can accomplish
the same:
find-classes() {
ag -oH --nocolor --noheading --nofilename
'[A-Za-z0-9-]+\-(?=.*[0-9])(?=.*[a-f])[a-f0-9]{5}'
}
I like to find those classes present in my CSS but not present in my views with
a simple process substitution and diff
:
diff <(find-classes css/*) <(find-classes views/*)
Another interesting read was CSS at Lonely Planet, the highlights for me were:
I sometimes want for variables with this system, which seems like a common theme
and driving reason for the adoption of pre-processors. I think instead what I
will aim for in the future is the use variable-like classes, in the vein of
clrs.cc (.blue-998bc
and .bottom-border-c61c9
).
And most recently, Medium's CSS is Actually Pretty Fucking Good. The honesty of how far they had to come was refreshing and there were some interesting ideas here that I hadn't see before or that echoed my own sentiments.
This system matches my personal style of development and avoids the need for complicated tooling. It does lack some of the niceties other systems provide but I think that forces me to assess what I include in a project. It allows for quick audits on a CSS code-base and avoids the specificity conflicts present in some traditional systems. I'll continue to follow emerging trends, but for now I think I manage okay with simple, unique CSS.