Approaching CSS the OO Way
In an interview somewhere in the web development industry:
"Hey, have you heard of CSS?"
Oh yeah! Totally... it’s that stuff that designers write right? You know it makes things pretty?
"Yeah, that’s the stuff. Can you write it?"
Sure... I mean designers can right? They don’t have CS degrees, so yeah I can.
"Perfect. You’re hired."
Sometimes I wonder if this is actually how our industry thinks about CSS. Sometimes I am pretty sure it is, and that makes me cringe. Not inside, but physically cringe. I am doing it right now...
Because it makes me cringe, I want to talk about why it is totally incorrect. I want to explore why this perception, of CSS as a designers language with no basis in Computer Science, is costing us headaches, money, and an innumerable amount of time. Because, the truth is, CSS should be written using the same mindset that any developer brings to creating objects or database tables. In fact the ideas of atomization and normalization from DB architecture are excellent parallels to how we should be approaching authoring CSS.
Before we look at how SOLID applies to CSS let’s talk about the C of CSS for a second. Cascade. We’re not talking about the mountain-stream-in-spring-filled-with-snow-melt variety of cascade. What we are actually talking about is the Inheritance model of CSS. Hopefully, inheritance model just woke you back up, because this thing is incredibly powerful.
Without going into the details of specificity the Cascade allows us to inherit styles from not one or two rules, but from as many as we want. Hold onto that idea for a second. That means that if we have 4 rules that govern different aspects of a DOM elements style, they will all be reflected in that element’s visual display. Specificity will decide which aspects of the rules get overridden by other rules if they overlap, and these two things mean that we have an incredibly flexible inheritance model.
Enough about object genealogy... let’s talk about how SOLID applies here.
The Single Responsibility Principle says that “every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class”. This applies directly to CSS. When you write a class in CSS it should have a single responsibility, and that responsibility should be encapsulates in the class. For example, if I have several items that need rounded corners (4px) I would write a class named round-corner-4 that looks like this:
.round-corner-4{ border-radius:4px; }
All border radiuses of 4px can now be handled by this single class, regardless of what other classes are applied to the DOM element. The class does one thing, and it does it for every DOM element that needs it.
The next principle is Open/Closed and this is essentially free in CSS. Classes are always open for extension, and their properties are essentially immutable. This means that we can extend each class by creating a more specific class (think specificity again...) that overrides its properties. You aren't modifing the underlying class, but you are extending it's functionality and changing it as needed.
This brings us to Liskov Substitution. This one took me awhile to figure out, and may be the weakest example of any of the SOLID principles. Liskov substitution says that you should be able to use any object that is a subtype of another object in place of the object it is a subtype of, without any issues. I had to re-read the wikipedia page a ton before I finally found the example at the bottom and started to understand this one.
So Liskov and CSS, remember this is a bit of stretch, boils down to “any class of a given type should be able to replace any other class of the same type without any adverse side effects.”
What?
Let’s say we create a font class called sans-serif, that dictates that the font face for anything it is applied to is sans-serif. If we have another font face class, we’ll call it serif, then we should be able to replace .sans-serif with .serif on a DOM element and not have any issues. This leads to very atomized classes with very specific jobs. Which is a great thing.
I. Interface separation... so this one really doesn’t have anything to do with css. If we stretch it like a batch of taffy we might be able to say something like: your DOM shouldn’t need classes that it doesn’t need in order to look right. But, if you are already writing nicely SO classes then you are already doing this. So... on to the next one.
D stands for definitely doesn’t apply to CSS. Actually it stands for Dependency Inversion, which really doesn’t have any real application in CSS as far as I can tell. If I think of one I will write it up.
It turns out that what this article is really about it writing simple, concise, focused CSS classes and applying lots of the to your DOM. Mostly it’s about the SOL of SOLID. Writing good CSS is hard. It takes thought, it takes planning, it takes refactoring, and it takes thinking about things from the framework of classical Computer Science. CSS is a beautiful thing when well written. It is flexible, powerful and fun to work with. So stop slapping your CSS together to make it “look right” and start writing well thought out CSS that will be easy to maintain and extend for years to come.
If you enjoyed this article please share it! Also, I have a newsletter that you might enjoy as well. Thanks! -Daniel