Object Oriented CSS (OOCSS) And Being Generic With Your Base CSS Classes
I recently learned a great CSS lesson when working on a large, multi-tier educational application. One of the entities in the application is a "School." A while back, the staff members using the application decided that they wanted to be able to archive schools and furthermore, if the school was archived, they wanted it to be really obvious on the school's detail page. As such, I went into the code and added something like this to the top of the page:
<!--- Output school archive message. --->
<div id="archived-school-message">
<div class="message-content">
This school was archived on 03/01/2009
</div>
</div>
At first, this worked great and the staff members were all happy. But then, a few weeks ago, they came back and said that they didn't like the term "archived". Really, what they wanted to do was to think of schools as having an Active / Inactive status. To align the software with this intent, I went and changed the school's detail page:
<!--- Output school active status. --->
<div id="archived-school-message">
<div class="message-content">
This school was deactivated on 03/01/2009
</div>
</div>
To the staff members, this was perfect - the application looked like they wanted it to look; but, to me, this was a semantic nightmare! Now, I have some CSS element called "archived-school-message" referring to something that is deactivated / inactive. In order to keep the CSS meaningful, I was going to have to change my CSS definitions to use something like "school-status-message" instead of the now-meaningless, "archived-school-message."
Before updating my CSS file, I took a moment to really think about the situation and how I got here. What I realized was that the root of the problem was not the shift in business requirements - the root of the problem was that my original CSS class was too specific; it described a single use-case and not the true intent of the CSS module.
Ever since I watched Nicole Sullivan's presentation on Object Oriented CSS (OOCSS), I've been trying hard to think in terms of generic modules and the use-cases that might extend them. The more I play around with her idea's the more I like them and find them to be very flexible. Taking Nicole's ideas and applying them to my current situation, I went and created a generic CSS class, "warning-message-box." This CSS class would be the generic base template for all warning boxes. The updated HTML with this generic class now looks like this:
<!--- Output school archive message. --->
<div class="warning-message-box">
<div class="message-content">
This school was deactived on 03/01/2009
</div>
</div>
Right now, I am operating on the assumption that all warning message boxes will be the same. But, if they ever need to be specialized, rather than creating a totally new class, what I would do is create an extending class that simply modifies the base class. So, if the school status message box ever needed to be different (ex. have a different font color or background image), I would create the additional class, "school-status-warning-message-box." Then, rather than replacing the generic message box class, I would extend it within the markup:
<!--- Output school archive message. --->
<div class="warning-message-box school-status-warning-message-box">
<div class="message-content">
This school was deactived on 03/01/2009
</div>
</div>
Here, you can see that the parent div (the module container) has both the base class and the extending class which adds only the use-case-specific properties for the module.
Of course, with the extending base class, we still need a class name that is tied to the use-case - this is the same problem we had in the beginning. I guess, my point with this post was not really to tell you how to completely remove the coupling of your CSS class names to the code in which they are used; the ultimate point of this post is two fold: One, whenever you create a class, take a moment and think about how you might make it more generic to cover several similar use-cases. And two, when you have a specific use case, consider using Object Oriented CSS techniques to extend the base class rather than replacing it completely.
Want to use code from this post? Check out the license.
Reader Comments
Coming in a bit late . . . but I've been wondering - is OOCSS really ready for prime time? In other words, can it be used on a public, large site and not have everything break down?
@Lola,
At the end of the day, OOCSS is simply CSS with a framework mentality. As such, there's nothing about it that would limit you on any kind of large or small site - the technology is the same.
To me, the thing that might be the most limiting is the size of the class names. Now, in Nicole's presentation, her class names are relatively short and then she uses contextual selectors for nested classes. I have mixed feelings about that as it can lead to unexpected cascading. As such, I tend to make my class names longer and more specific rather than relying on the cascading nature. It's basically a trade-off - I will suffer less unexpected cascading, but will have to deal with larger class names.
@Lola & Ben,
In answer to the question if OOCSS can be used on a large site- the answer lies in one website http://jqueryui.com/.
If you have ever looked at the CSS that the UI uses, you will notice that there are base classes all over the place, and then each individual module extends those classes in some way. Of course it isn't actually called extending, but that in essence, is what is done.
@Brandon,
Good point. jQuery UI has a very robust CSS framework that does work every much in a class hierarchy sort of fashion.
Your CSS classes seem kind long. Why do that? Why not the first div be class="warning school". One class for school to define what a "school" looks like and another class for "warning" for what a warning looks like. Warning should embellish school. Warning should just contain the difference.
@Glen
If you shorten your class names too much, like one word keywords, you are going to run out of keywords and have ambiguity. For example; with your class school that extends message, what are you going to call the classes for school menus and school details?
naming, whether in programming or UI or CSS certainly takes practice. Get it right and you have something you can work with. Get it wrong and its a pain for a long time.
One technique is to do a first draft of "it" quickly and then throw it away. The second try will always be much better.
There is no magic bullet of naming. Practice certainly helps.
Ben,
Should you not have went even more generic with your classes? I know you're making assumptions but I'm trying to follow you here. Would it not have been better to have a class of "message_box" and then extend that for errors, success, etc... (then you could extend that for something like "school_error", "form_error", etc...
Thoughts?
@Justin,
That's an interesting point. I think that's the threshold where the "OO" aspects of the CSS framework start to break. From an "object" stand point, each extending object can add it's own members to the object class. With CSS, however, we only have the ability to override formatting - we don't have the ability to add new members (markup elements). As such, I think there are classes that simply have different contextual elements.
But, perhaps, there is nothing wrong with adding new markup for different classes. Like maybe something like:
Base class:
<div class="message-box"></div>
Extending class:
<div class="message-box error-message-box">
. . <div class="error-message-box-header"></div>
. . <div class="error-message-box-content">
. . . . Here is a Message!
. . </div>
. . <div class="error-message-box-footer"></div>
</div>
In this example, not only does the extending class take the base class name (message-box), it *also* add new nested markup. So, in that case, I suppose you could make the base class more generic.
To be honest, I don't really know. I think In OOCSS, Nicole gives most all modules a header, footer, and body container. I need to take some time a re-read her documentation.
@Glen,
This is definitely something that I've struggled with. On the one hand, I don't want to run out of meaningful names as @Andrew said. I also want to try to avoid any unexpected cascading. Like you said, there is no magic naming scheme. It comes down to practice and perhaps doing quick drafts of pages and then cleaning up the CSS later? I don't really know.
Hi Ben,
This is a great step by step article and intro to thinking differently about class names, I like it. This is actually how I came to the principals of OOCSS (by building things and seeing how they break, and finally finding more robust solutions).
I do use short class names, but you'll notice that some of them are like "protected" values. I only change them within the context of another object. For example, a list might have a class first that removes a border from the first element, but I don't write:
.first{border:none;}
I write:
.actionList .first{border: none;}
mainly because first can mean different things in different contexts. Any object can use this "keyword" but only within its own scope.
Oh, and head and foot are optional regions of a module, not required.
@Justin, yes, I like what you are thinking. I've done:
.message{...}
.error { extends: .message; ... }
.warning { extends: .message; ... }
.help { extends: .message; ... }
They shared CSS (positioning an icon etc) but had different colors/img.
Cheers,
Nicole (stubbornella)
There are many ways of organizing your CSS and what NOT to call your classes and ID's, so I don't see how this OOCSS is "new". But it is interesting to know someone has put this way of organizing your CSS into writing. Many a programmer could learn from it, that's 4 sure!
@Nicole,
I like the idea of using shorter names, but only for ease of typing. I think from a functional standpoint, it asks sometimes too much of the developer to understand the full breadth of the CSS architecture. If one of the goals of OOCSS is to allow new developers to jump in on a project and just start adding modules without messing things up, I think using longer, more explicit names would prevent unexpected cascading (at least until we have direct-descendant selectors fully compatible).
This can lead to longer names, but perhaps less chance for confusion. For example, I could certainly image an element with class "first" containing other elements with class "first" nested deeper.
But like @Glen said, it's an art form to naming CSS.
@Sebastiaan,
Agreed - from a technological standpoint, there is nothing new going on here. It's simply a more standardized way to organize CSS modules.