On a large project, CSS often becomes messy and difficult to maintain. Selectors get longer and longer, reaching deeper and deeper into the DOM. Properties override each other. Fonts and colors have to be specified for just about every element. And the dreaded !important
begins to rear its head.
Before long, team tension is palpable. Fortunately, there’s a better way.
Much of the trouble with CSS stems from long, difficult-to-disentangle selectors. However, at last March’s SoftwareGR, Jonathan Snook recommended limiting selector depth, a habit I’ve been practicing on my current project. It’s had some interesting effects on how I write CSS. In general, it’s pushed me to specify the app’s design—not in CSS—but in HTML. Allow me to explain.
At the lowest level, you can style HTML elements using the style
attribute. This is inconvenient and terrible, but swinging to the other end of the spectrum isn’t much better: labeling each element with a single HTML class, styling it with CSS, and making exceptions to the rule by adding parent selectors.
Here’s an example rule, and an exception:
.user {
font-size: 14pt;
}
.homepage .user {
font-size: 18pt;
}
This strategy gives your CSS knowledge of both your page structure and your whole application. The larger and more complex the app, the longer and deeper selectors tend to be. To follow Snook’s advice and keep selector length to a mininmum, I’ve started specifying rule exceptions in the HTML by adding more classes to elements.
There’s no reason the stylesheet needs to know that .user
elements are bigger on the homepage, only that some .user
elements are, in fact, bigger. So instead of the above CSS, I write:
.user {
font-size: 14pt;
}
.user.big {
font-size: 18pt;
}
Any .user
elements that need to be bigger now have a simple way to achieve that, and it’s completely independent of the element’s ancestors. Rather than using the style
attribute to specify each low-level property on an element, we can use the class
attribute to specify its high-level design properties.
Instead of thinking of the class
attribute as labeling an element, think of it as describing an element. For instance, .bright
, .muted
, or .stacked
are all general-purpose descriptors. In fact, they’re adjectives. Prepositional phrases are also useful for describing elements: .below-header
, .above-footer
, .with-dropdown
, .in-column
. Verbs, too, can be helpful: .opens-sidebar
or .slides-away
.
In keeping my CSS selectors short, I’ve converted my HTML classes from element names into descriptions of elements. This div
isn’t days-since-last-login
, it’s small muted text-right
. That button isn’t the number-of-alerts-button
, it’s a big shadowed two-part alert button
. Besides reducing the complexity of the CSS, it makes the HTML much more descriptive and meaningful.
In literature, there’s a term for using so much description. It’s called “purple prose.” It’s frowned upon in literary circles, but in the last few months, I’ve discovered just how useful purple prose can be for writing shallow, composable, modular, and re-usable CSS rules. I highly recommend it!