Object Oriented CSS (OOCSS) and Sass

Object Oriented CSS (OOCSS) with Sass

This entry was published on December 2, 2015 and may be out of date.

The concept of Object Oriented CSS was conceived by Nicole Sullivan and has since become one of the most widely adopted methodology of writing neat and manageable CSS. The objective of this methodology is to make CSS as reusable as possible by making it modular and generic. The mantra is Don’t Repeat Yourself (DRY).

“Object Oriented” CSS

The term “object oriented” is rooted in software engineering where it means organising code around ‘objects’ rather than procedural actions, and data rather than procedural logic. The term is applied to CSS not in the strictest engineering sense, but almost as a metaphor.

In OOCSS, a CSS object is a repeating visual pattern, i.e. a pattern that would produce the same results visually regardless of where it is placed. Let us take a CSS object such as a button, which happens to be placed inside a sidebar.

<div class="sidebar">
  <a class="btn" href="/">Click me!</a>
</div>

In procedural styling method, we would do something like this:

.sidebar {
  width: 200px;
  margin: 0;
  padding: 10px;
}

.sidebar a.btn {
  display: inline-block;
  padding: 6px 12px;
  margin-bottom: 0;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  text-align: center;
  white-space: nowrap;
  vertical-align: middle;
  cursor: pointer;
  background-image: none;
  border: 1px solid transparent;
  color: #fff;
  background-color: #5cb85c;
  border-color: #4cae4c
}

As seen here, the styling is entirely dependent on the HTML, i.e. if the markup were to change, the CSS would become entirely obsolete. To to put this another way, if the button was moved out of the sidebar, the CSS would no longer apply.

Secondly, the CSS is not reusable, i.e. if another object with the same visual pattern appears elsewhere, the code would require repetition. This repetition, in turn, makes CSS unmanageable in the long run.

Therefore, in order to achieve the much needed manageability, our objectives ought to be are modularity and reusability. OOCSS provides two brilliant methods for achieving such results.

Separation of container and content

In order to address the aforementioned concerns, we separate the container (the sidebar) and the content (button) as two separate repeating visual patterns. By making them distinct from each other in the CSS, both elements become reusable objects.

.sidebar {
  width: 200px;
  margin: 0;
  padding: 10px;
}

.btn {
  display: inline-block;
  padding: 6px 12px;
  margin-bottom: 0;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  text-align: center;
  white-space: nowrap;
  vertical-align: middle;
  cursor: pointer;
  background-image: none;
  border: 1px solid transparent;
  color: #fff;
  background-color: #5cb85c;
  border-color: #4cae4c
}

The button is now a visual pattern that can be placed anywhere in the document with the same results. Secondly, if the button is moved out of the sidebar, we would not have to change any CSS. If changes are made to the module, all instances of the button across a site would uniformly reflect the changes, thereby bringing much needed visual consistency without the need to repeat ourselves.

Let us consider another scenario where there are multiple colour schemes and buttons that come in multiple colour variations. Would it still be possible to maintain our DRY philosophy? This is when the second directive of OOCSS comes in.

Separation of structure and skin

Structure refers to the CSS properties that relate to its dimensions and position.

Imagine a wireframe of a button drawn either with pen and paper or with a wireframing tool. Wireframes, by nature are the bare-bone structure of the elements, which would only contain the properties relating to dimension and positioning of the element include height and width, padding and margin, the text and font properties such as the font size, line height and text alignment etc. When wireframing, only the structure of the element matters.

When the wireframe is converted to a colourful button in the final design, it will most likely contain some further properties, that are only visual, that build on top of the existing structure, such as the text colour, the background colour and border colour, etc. OOCSS essentially brings the same principle to CSS. i.e. all the structural properties of an element would be contained as the default settings, whilst the skin-related properties would be separated.

OOCSS Separation of Structure and Skin

Structure

.btn {
  display: inline-block;
  padding: 6px 12px;
  margin-bottom: 0;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  text-align: center;
  white-space: nowrap;
  vertical-align: middle;
  cursor: pointer;
  background-image: none;
  border: 1px solid transparent;
}

Skins

.btn-primary {
  color: #fff;
  background-color: #337ab7;
  border-color: #2e6da4;
}

.btn-success {
  color: #fff;
  background-color: #5cb85c;
  border-color: #4cae4c;
}

With the skins separated from the structure in CSS, we use the following markup whenever necessary:

<a class="btn btn-primary" href="/">Button</a>
<button class="btn btn-success" type="submit">Button</button>

Our code above is starting to look a lot like Bootstrap; That is because it is. Bootstrap, perhaps the most popular framework in the world, uses these very practices throughout.

Limitations

The markup shown above is non-semantic. Semantic HTML markup is supposed to convey meaning, or semantics, rather than to define the presentational aspects. What we are doing in the aforementioned example is to add a non-semantic btn-primary class, which only serves a presentational purpose, therefore being non-semantic.

How about a case when we have to change the colour of a button, say, from btn-primary to btn-danger? It would require the modification of HTML for every instance of the button in the markup. In our pursuit of scalable and reusability of CSS, we managed to make our markup hard to maintain.

It may not be such a huge problem for small to medium sized websites and web apps, but for sites that include thousands or more pages of content, this limitation might as well become a problem.

This has been the biggest complaint with Bootstrap so far, that the vanilla framework makes developers use non-semantic code all over their projects.

Sass comes to the rescue

We are going to break away from the Bootstrap convention and try to solve the problem of semantics with Sass. The objectives are to always have HTML classnames that make sense in any context. Rather than .btn .btn-primary, we are going to use meaningful names such as .btn-call-to-action, .btn-product-details and so on.

But first, we need to port the CSS structure (.btn) and skins (.btn-primary and .btn-success) as Sass mixins.

We need write parameter-less mixins. The urban myth that mixins with no parameters are bad, is a lie.

@mixin button {
  display: inline-block;
  padding: 6px 12px;
  margin-bottom: 0;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  text-align: center;
  white-space: nowrap;
  vertical-align: middle;
  cursor: pointer;
  background-image: none;
  border: 1px solid transparent;
}
@mixin button-primary {
  color: #fff;
  background-color: #337ab7;
  border-color: #2e6da4;
}
@mixin button-success {
  color: #fff;
  background-color: #5cb85c;
  border-color: #4cae4c;
}

You might be wondering why not use the @extend directive. Because it happens to be quite problematic. I know these buttons have the same context which makes it a use-case for the @extend directive. But there are far more pitfalls, which makes mixins a vastly superior choice in any case.

1. When to use @extend; when to use a mixin by Harry Roberts
2. Methods for modifying objects in OOCSS by Oliver Jash
3. When I use (and Don’t Use) Sass Extend by James Steinbach
4. Sass: Mixin or Placeholder by Hugo Giraudel

Consider the following case with two buttons, used as call-to-action and product details, which have been named semantically as such:

<a class="btn-call-to-action" href="/">Buy Now!</a>
<a class="btn-product-details" href="/">Find out more..</a>

We are then going to apply our mixins to style our buttons.

.btn-call-to-action,
.btn-product-details {
  @include button;
}

.btn-call-to-action {
  @include button-primary;
}
.btn-product-details {
  @include button-success;
}

The CSS that it exports:

.btn-call-to-action,
.btn-product-details {
  display: inline-block;
  padding: 6px 12px;
  margin-bottom: 0;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  text-align: center;
  white-space: nowrap;
  vertical-align: middle;
  cursor: pointer;
  background-image: none;
  border: 1px solid transparent;
}

.btn-call-to-action {
  color: #fff;
  background-color: #337ab7;
  border-color: #2e6da4;
}

.btn-product-details {
  color: #fff;
  background-color: #5cb85c;
  border-color: #4cae4c;
}

Conclusion

OOCSS with Sass is an indispensable methodology to my development process. There is a little learning curve in the beginning and it takes a bit of getting used to. But once adopted, this methodology provides a tremendous amount of flexibility and clarity to CSS code, which makes development not only faster in the long run, but it helps maintain sanity.

Further reading

  1. Documentation of OOCSS by Nicole Sullivan
  2. OOCSS + SASS = The Best Way to CSS by Ian Storm Taylor
  3. Using OOCSS with SASS by Jaime Caballero at TheSassWay.com
  4. An Introduction to Object Oriented CSS by Louis Lazaris at SmashingMagazine.com
  5. Object-Oriented CSS: What, How, and Why by Andrew Burgess at TutsPlus.com