Writing Modular and Reusable CSS
When I heard Nicole Sullivan talk at CodeConf back in April, I was intrigued by the case study she did while working at Facebook.1 I’ve wanted to try a similar approach to writing CSS for quite some time, but I’ve yet to work on a project where high-performance, modular CSS was a priority.
So I’m writing this tutorial. I want to see object-oriented CSS (OOCSS) in practice; if you’re interested, too, follow along.
The rest of this article assumes at least some familiarity with CSS and object-oriented programming concepts.
Our Project
It’s Twitter for movies! [obligatory groan] The design we’ll be working on is for a fictional movie review site that lets you post pithy remarks about films you’ve seen. Here’s a very basic wireframe.

To get started, let’s dissect it from a high-level.
Commonalities
Modularity implies that we need parts of a page that can be treated as discrete elements. But we also want our CSS to be abstracted enough that it can be reused for multiple elements. In looking at this (very) basic wireframe, we can already see some parts of the page that are similar.

As the wireframe transitions to a mockup, the added fidelity lets us spot even more commonalities.

And if you’re a bit flexible in defining similarities, you’ll see that certain parts, like the Following box and the Trending box, are identical (save for the alignment of an image or two).

Writing the Code
Nicole Sullivan recommends keeping your selector chains short. The shorter the selector chain, the faster the browser can parse your CSS. There are technical reasons for this, but that goes beyond the scope of this article. If you’re interested, you can read the nitty-gritty details at Google Code.
Suppose you want to target the star ratings in the review boxes. You could use something like this:
section#reviews div.review div.rating { ... }
But—assuming you aren’t using the .rating class anywhere else—you could safely shorten it to:
div.rating { ... }
The div part isn’t necessary for this selector either since we want the .rating class to be reusable and extendable. So, simplify it:
.rating { ... }
Now, if we want to write exceptions to this rule, we can target specific elements that have this class applied to them.
span.rating { ... }
Breaking It Down
First, let’s identify which parts of the page are similar enough to be grouped together into a single CSS rule. In object-oriented-speak, we’re defining a parent class or parent object.
The profile, trending, following, and review boxes all contain similar elements.

We’ll start with the profile box.
Note: If you want to skip ahead, I’ve posted all of the code for this project on Github. There’s also an online demo.2
The CSS
The parent class for all of these objects will be called .itembox. This isn’t terribly semantic, but the descriptor has to be generic, as it describes an item that can contain a link to a movie, a person’s profile, or an entire movie review.
Here’s the CSS for the user profile in the profile box:
.itembox img, .itembox h3, .itembox p { float: left; }
.itembox img { margin-right: 10px; }
.itembox h3 {
margin: 0 0 10px 0;
width: 150px;
}
.itembox p { font-size: 1.3em; }
.itembox .profile_button {
float: right;
margin: 0;
}
The .itembox class contains several elements, including images, an H3, and a paragraph tag.
Now that we have our default parent object defined, we can extend it (i.e., subclass it). Here’s the CSS for each user in the Following box:
.itembox.following { margin-bottom: 10px; }
.itembox.following img, .itembox.following p {
display: inline;
float: none;
vertical-align: middle;
}
Just as with object-oriented programming, the items in the Following box inherit from the parent class .itembox and override functionality where necessary. In this case, we’re extending the parent class by adding a bottom margin to the row and adjusting the layout of images and paragraphs that appear in each row.
Creating the movie list in the Trending box is pretty straight-forward:
.itembox.trending {
font-size: 1.2em;
margin-bottom: 5px;
}
Again, we’re just overriding the defaults that were established in .itembox.
Finally, here’s how we create each row of the review list:
.itembox.review { margin-bottom: 20px; }
.itembox.review p { margin-top: 8px; }
.itembox.review h5 { margin-bottom: 2px; }
The movie reviews contain a few extra elements. Specifically, the title is an H5, and we’ve included rating stars. These features are necessary for the review subclass, but they might also end up being useful for future iterations or subclasses of the main .itembox class, so let’s update the parent class with these features.
.itembox img, .itembox h3, .itembox h5, .itembox p { float: left; }
.itembox img { margin-right: 10px; }
.itembox h3, .itembox h5 {
margin: 0 0 10px 0;
width: 150px;
}
.itembox h5 { width: 580px; }
.itembox h5 span { font-weight: normal; }
.itembox p { font-size: 1.3em; }
.itembox .profile_button, .itembox .stars {
float: right;
margin: 0;
}
That’s it! Four discrete page elements constructed with about 26 lines of CSS.
Writing good CSS starts with being able to see the constituent parts of a page—where the boxes are. One way to get good at this is to use the Web Developer Toolbar for Firefox. It allows you to outline all block-level items on the page, which looks like this:

But good CSS requires more than spotting boxes. As @stubbornella puts it, it’s about pattern recognition. In our example above, we noticed the box pattern that included images, some descriptive text, and a couple of links. These things might not always appear in the same order (or at all), but they always appear in the same group.
After this exercise, I’m an OOCSS convert. It took less than 8 kilobytes of HTML and CSS to construct a reasonably complex layout. That’s pretty impressive, and—looking at it now—it could probably be simplified even further. Figured out a way to streamline it? Leave a note in the comments.
If you’ve found this intriguing and want to read more about OOCSS, have a look at the project’s FAQ on Github.
View a working demo of the example project.
View the example project’s source code on Github.
UPDATE: I’ve written a follow-up article on how to add IE8 support to this project, and an additional post discussing the HTML used to create this demo.
3 Notes/ Hide
-
bergjuiceles liked this
-
purblindintr liked this
-
insertionshotsmother liked this
-
religiosityd liked this
-
newsdisrepai liked this
-
smothercrazybukkake liked this
-
renaissancenerd posted this