Simple, Unique CSS
2016-03-20I 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.
It's Not My Fault
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 jived 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.
What Does It Look Like?
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.
How Is It Accomplished?
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.
Why?
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/*)
Further Reading
Another interesting read was CSS at Lonely Planet, the highlights for me were:
- "Our use of Sass's features is pretty low, mostly limited to variables and a few mixins"
- "We use a version of BEM to distinguish between components and prevent style collisions"
- "We don't use IDs in CSS. We very rarely style anything but classes"
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.
- scales as a way to standardize the use of z-indexes and colors
- "Limit LESS to variables and mixins (no nesting, guards, extend, etc.)"
That's Nice But...
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.