I think that OOCSS by way of your example is an anti-pattern that does not provide a clear separation of concerns (html vs css) and does not provide you with semantic html nor css.
The separation of concerns is that HTML is concerned with the structure of a document, while CSS is concerned with how that document is presented.
<button class="green rounded no-border">Save</button>
<button class="grey rounded no-border">Cancel</button>
With the following css:
.green {
color: #0f0;
}
.grey {
color: #777;
}
.rounded {
border-radius: 5px;
}
.no-border {
border: none;
}
Violates this separation of concerns by having the HTML document indicating that the save button should be green (instead of CSS telling it).
While OOCSS is designed to reduce the amount of code you write, it ends up being a maintenance nightmare by having to declare many (not semantic) classes. Suppose you want later all your save buttons to be blue instead, are you going to change your green class to be blue, or are you going to do a ctrl+f
in all your source files and update the text green to blue?
A good way to introduce reusability while still retaining semantic HTML / CSS is to use a CSS compiler (like less.js for example).
<button class="primary-action">Save</button>
<button class="cancel-action">Cancel</button>
With the following less.js:
/* these are reusable variables */
@primary-action-color: #0f0;
@cancel-action-color: #777;
/* this is a re-usable "mixin" */
.rounded() {
border-radius: 5px;
}
button {
border: none;
.rounded;
.primary-action {
color: @primary-action-color;
}
.cancel-action {
color: @cancel-action-color;
}
}
While it is more code initially, when you start reusing these variables / mixins you will be able to benefit from the semantic HTML and organized CSS. For example, because the cancel-action
has a good meaningful name, you can already add functionality to your app that makes sense. Take for example the following jQuery.
$("button.cancel-action").click(function(e){
if (!confirm('are you sure you want to cancel?')) {
e.preventDefault();
}
});