UX Design and Development course

Object Oriented Cascading Stylesheet (OOCSS)

OOCSS is built upon two main principles:

  • Separation of structure and skin
  • Separation of container and content

To better understand these principles, let's take a look at what OOCSS is and what it is trying to solve.

What is OOCSS?

A concept established by Nicole Sullivan with the idea being very simple; write CSS that is scalable, maintainable, and semantic. In a nutshell - object oriented. OOCSS by itself is a powerful tool. OOCSS combined with Sass, is even a more powerful tool.

Repeating patterns in your stylesheets lend themselves to the creation of objects which can be sub-typed or super-typed. These patterns can be polymorphic, thus infinitely reusable through inheritance.

Unruly CSS written without the forethought of OOCSS can have any or all of the following problems:

  • Writing styles based on the view or the components as a whole can lead to bloated CSS
  • Lack of global defaults will lead to repeating style patterns, adding more bloat
  • Incorrect use of selector inheritance combined with heavy bloat can lead to poor CSS performance and typically exaggerated use of the !important tag

In this section, I will discuss how to avoid these issues by properly implementing the tenets of OOCSS. This will allow you to create a well established framework that, when combined with Sass, will allow you to further enhance the scalability, maintainability and re-use of the CSS.

To better understand OOCSS, we must be able to breakdown our design into small re-usable components. In order accomplish this task, we must understand what is a CSS object.

CSS Object

Think of your CSS as a bicycle assembly line using individual objects like wheels, handlebars, brakes, and seats. Our assembly will produce the final product, a bicycle. There will be slight variations on some of the objects, for example size of the wheels or color of the frame, which are issues that can be handled along the assembly line.

In order to efficiently assemble the bicycle, the original prototype is broken down into its individual pieces and the assembly. These individual parts are analyzed and the assembly line is created in order to efficiently put together the bicycle. A very similar concept can be applied to CSS. The design is analyzed and broken down into its individual working pieces. These CSS Objects are created in order to be re-used on the site, or our assembly line. The final product, the implementation of the design, is the culmination of the individual CSS objects. The OOCSS wiki further explains CSS objects as:

"A CSS object consists of four things: HTML, which can be one or more nodes of the DOM, CSS declarations about the style of those nodes all of which begin with the class name of the wrapper node Components like background images and sprites required for display, and JavaScript behaviors, listeners, or methods associated with the object."

This can be confusing because each CSS class is not necessarily an object in its own right, but can be a property of a wrapper class.

Let's take a closer look at a section heading example. We can write the heading CSS like this:

#container h2 { /*IDs limit use of rules*/
/* Over-qualification with h2 tag restricts use to only this element */
  font-size: 2em;
  line-height: 1em;
  margin: 0.25em;
  color: #CFC35D;
  font-family: Verdana, Arial, sans-serif;
}

An issue with the above code is that it is an over-qualified selector that is limited to a h2 element that is nested within #container. When the same or slightly similar style needs to be applied in another area, the footer for example, I will have to duplicate the CSS rules as such.

#footer h2 { /* Only difference between this and the previous style is the font-size and extra margins. */
  font-size: 1.5em;
  line-height: 1em;
  margin: 0.25em 0.5em;
  color: #CFC35D;
  font-family: Verdana, Arial, sans-serif;
}

The following is an example of a repeating pattern that can be abstracted as one or several CSS objects to be used individually or as an assembly of styles. First I need to abstract some of the styles to the default globals section.

The following selectors will create CSS rules that are applied to base elements like the body and h2. These rules are no longer assigned to an over-qualified selector as before. However, more minute styling needs to be created in order to finalize the desired display.

body {
    font-family: Verdana, Arial, sans-serif;
}
h2 {
    font-size: 2em;
    line-height: 1em;
}

At this time, it is prudent to have an understanding of what the style is supposed to be used for and what it will represent. In this case, we are trying to create a header style for a section on the site. This knowledge will help us not only create the style, but also give it a semantic class name.

body { /* The font-family, which is usually applied on the entire site, is applied at the body. */
    font-family: Verdana, Arial, sans-serif;
}
h2 { /* The <h2> element has CSS rules that will be applied anywhere the element is used. */
    font-size: 2em;
    line-height: 1em;
}
/* The new semantic class .section-header reduces the font-size and increases margin-left and margin-right. This new selector can be applied anywhere, including the footer, which will override the <h2> base element rules. */
.section-header {
    font-size: 1.5em;
    margin: 0.25em 0.5em;
    color: #CFC35D;
}

The above example is a simple implementation of OOCSS. As we can see, the design of a section header has been broken down into it's individual styles and CSS objects have been created accordingly. Continuing, I will look further into the OOCSS guidelines and how to properly implement them.

OOCSS Guidelines

Now that we are familiar with the building blocks of CSS, a CSS object, we will dive further into the guidelines of OOCSS. We delve deeper into the two main principles of OOCSS:

  • Separation of content from container
  • Separation of structure from skin

Implementation of OOCSS requires not only to follow the mentioned principles but also the prudent review of the design and understanding the containers, content, structure and skin. Let's take closer look at these guidelines and principles.

Separation of content from container

The main culprit that violate this guideline are location dependent styles. A simple example of location dependent style is something like this:

.footer a {
  color: #ccc;
}

This example is applying a gray color to the anchor tag in the footer (or the anchor tags that are children of an element with the class of .footer). This will limit the usage of this style (although it should be noted that this style can be used outside of the footer, however this will make the style non-semantic and confusing). The correct approach is to allow the default style of the anchor tag be applied to it and create a style to override and apply the needed change.

a {
color: blue;
}
.footer-link {
  color: #ccc;
}

Let's take a look at a more complicated (and more wrong) example:

#content #mainInfo p img.left {
  float: left;
  border: 0;
  padding: 2px;
  padding-right: 25px;
}

This style will only be applied to the <img> element with a class of .left that is nested in a <p> element which in turn is nested in an element with the id of #mainInfo and which in turn is nested in an element with an id of #content. If we want to apply the same style somewhere else we will have to re-created this style all over and apply it specifically to that element. So, how do we fix this? First thing is to examine what it is that we are trying to accomplish. What we are trying to accomplish is to float the <img> element to the left. The question is, do we only want to float an <img> element? Most likely the answer is no. We want to create a style that is robust enough to be applied to any element. As a result the first class we are going to create is this:

.float-left {
  float: left;
}

The style of setting no borders on the <img> element is something that maybe we want to set for all <img> elements and the exception would be to add border to the <img>. As a result, our CSS styles would be:

img {
  border: 0;
}
.float-left {
  float: left;
}

To attack the padding, we must consider padding for the element on the entire site. If we think that all <img> elements should have a padding of 2px then this is a style that should be applied at the <img> element level and then the exceptions should be overridden. The same logic applies to all other elements like <div>, <section>, <ul>, etc... So in this case, I would amend the code to something like this:

img {
  border: 0;
  padding: 2px;
}
.float-left {
  float: left;
}

This style also needs a padding on the right hand side of 20px. In order to apply this desired effect, we must consider the two options that we have. First option is the consider what we are creating this padding. In this situation, let's say that these images are thumbnails for an image gallery that we will be lining up in order for the user to view and click on them to view a larger view of the image. Therefore in this case, we will create a semantic class and apply the padding style to it.

.gallery-thumbnail {
  padding-right: 20px;
}

Our other option is to create a series of styles that will allow us to override individual paddings (and margins) not only in this situation but also in all others. The OOCSS Github site has the following padding and margin CSS code:

/**
 * Spacing classes
 * Should be used to modify the default
 * spacing between objects (not between nodes of the same
 * object)
 * Please use judiciously. You want to be
 * using defaults most of the time, these are
 * exceptions!
 * <type><location><size>
 */
/* spacing helpers
p,m = padding,margin
a,t,r,b,l,h,v = all,top,right,bottom,left,
horizontal,vertical
s,m,l,n = small(5px),medium(10px),large(20px),none(0px)
*/
.ptn,.pvn,.pan{padding-top:0px !important}
.pts,.pvs,.pas{padding-top:5px !important}
.ptm,.pvm,.pam{padding-top:10px !important}
.ptl,.pvl,.pal{padding-top:20px !important}
.prn,.phn,.pan{padding-right:0px !important}
.prs,.phs,.pas{padding-right:5px !important}
.prm,.phm,.pam{padding-right:10px !important}
.prl,.phl,.pal{padding-right:20px !important}
.pbn,.pvn,.pan{padding-bottom:0px !important}
.pbs,.pvs,.pas{padding-bottom:5px !important}
.pbm,.pvm,.pam{padding-bottom:10px !important}
.pbl,.pvl,.pal{padding-bottom:20px !important}
.pln,.phn,.pan{padding-left:0px !important}
.pls,.phs,.pas{padding-left:5px !important}
.plm,.phm,.pam{padding-left:10px !important}
.pll,.phl,.pal{padding-left:20px !important}
.mtn,.mvn,.man{margin-top:0px !important}
.mts,.mvs,.mas{margin-top:5px !important}
.mtm,.mvm,.mam{margin-top:10px !important}
.mtl,.mvl,.mal{margin-top:20px !important}
.mrn,.mhn,.man{margin-right:0px !important}
.mrs,.mhs,.mas{margin-right:5px !important}
.mrm,.mhm,.mam{margin-right:10px !important}
.mrl,.mhl,.mal{margin-right:20px !important}
.mbn,.mvn,.man{margin-bottom:0px !important}
.mbs,.mvs,.mas{margin-bottom:5px !important}
.mbm,.mvm,.mam{margin-bottom:10px !important}
.mbl,.mvl,.mal{margin-bottom:20px !important}
.mln,.mhn,.man{margin-left:0px !important}
.mls,.mhs,.mas{margin-left:5px !important}
.mlm,.mhm,.mam{margin-left:10px !important}
.mll,.mhl,.mal{margin-left:20px !important}
.mra,.mha{margin-right:auto !important}
.mla,.mha{margin-left:auto !important}

The above code can be placed in a separate CSS file and imported into any CSS file as desired. It is ideal that the styles that are applied to an element tell the story of all the styles being applied. So I don't see any issue with substituting the class .ptn with .padding-top-none or .pbl with .padding-bottom-large. So in order apply the desired original style to the <img> element, the HTML will look something like this:

<img src='path/to/the/image'
alt='appropriate text' class='float-left padding-right-large' />

Or to apply the .gallery-thumbnail, it will look something like this:

<img src='path/to/the/image'
alt='appropriate text' class='float-left gallery-thumbnail' />

Separation of structure from skin

To build a site that the structure or the markup or the HTML separated from the skin or the style or the CSS, requires a lot of dedication and forethought. Prime example of this separation is the example of CSS Zen Garden. Zen Garden is a site that allows designers and developers to create new websites not by changing the HTML but by creating a whole new CSS.

In order to have a good grasp of this concept, let's create some individual building blocks for our site. Creating individual CSS objects that can be assembled to create the desired style is one of the main guidelines of OOCSS. One of the most commonly used and created CSS object is the container object (which also sometimes goes by the name of block object or panel object). A starting container object can look something like this:

.container{
  background: transparent;
  padding: 5px;
  box-sizing: border-box;
  width: 100%;
  height: auto;
  overflow: auto;
}

However there will subtle variation that will be extended or created to compliment or assemble other styles. For example in our online resume project, we have a container on the left, our side navigation bar, which has dark background and light colored text. As a result, we will create a style as such:

.side-nav {
  background: black;
  color: white
}

If a bordered container is needed then create a selctor like the following.

.bordered {
  border: 1px solid #cecece;
}
.main-content-bordered {
  border: 5px solid #b7d9a8;
}

It is the assembly of the individual objects that will allow for flexibility in creating individual components and that is part of the OOCSS process. As we get into more details, we can see that more assets can be added to individual areas. For example, a container may contain individual areas of header, footer, and body that can be expressed in the following way.

.container{
  background: transparent;
  padding: 5px;
  box-sizing: border-box;
  width: 100%;
  height: auto;
  overflow: auto;
}
.container > .head {
  font-size: 14px;
  font-family: 'Share Tech', Arial, sans-serif;
}
.container > .content {
  font-size: 12px;
  line-height: 1.4;
}
.container > .foot {
  font-size: 11px;
  font-family: 'Anaheim', Arial, sans-serif;
}

OOCSS is a great set of rules that will allow for a better built CSS framework. It will also help in reducing a tremendous amount of CSS bloat which in turn will help quite a bit in CSS and site performance. For further information on OOCSS visit OOCSS Github site.