May 26, 2023
• 6 min readIt’s 2023 and we have a lot of methods and techniques that make CSS writing better and easier. However, there is one method that was one of the first to tackle object-oriented CSS writing and lay a solid foundation for other frameworks that followed.
To avoid any misunderstandings, this method is no longer used (really only very rarely), but I thought it was good to understand the concept from which other methods derive, and that is the purpose of this article.
This method is called Object Oriented CSS (OOCSS) and, in this article, I will describe the basic principles and ideas of this methodology.
Introduction
In 2008, Nicole Sullivan borrowed the concept of object-oriented design to provide structure to CSS. She presented her Object Oriented CSS (OOCSS) concept at Web Directions North to the world.
The main idea behind OOCSS is to treat page elements as objects, assign classes to these objects, treat these classes as single entities in style sheets, and reuse them when necessary.
Object Oriented CSS is a methodology or framework for organizing and extending your CSS in a way that is lightweight, highly performant, and easily used by developers at all skill levels. — Ben Nadel
Basic principles
The idea of OOCSS is timeless. Nicole Sullivan started with the approach we use today when we create design systems. Take a look at Nicole’s presentation where she analyzes the websites of large companies such as Facebook and Salesforce and points out stylistic inconsistencies in their interfaces.
This approach might have also inspired web designer Brad Frost when he introduced the interface inventory method, which is based on similar principles but in a wider context and without reference to technology.
PNC bank has many button styles as Brad Frost described in his article “Interface inventory”.
The issue of inconsistent interfaces continues to be addressed today and will probably never be completely solved because there will still be new challenges and problems.
Although we already know how important it is to monitor consistency of the interfaces, we are still figuring out how to do it properly. This is also the reason why we build design systems.
We often associate this mental model with LEGO bricks.
However, this is an issue we need to solve if we want to improve the quality of our interfaces, save development costs, and speed up the entire design process. Nicole Sullivan had the same goal and her work took CSS writing a step further. Let’s take a look at the principles of her framework. This methodology defines a CSS object as a visual pattern that can be used throughout the site. It serves as a guideline when designing reusable code that is scalable, sustainable and easy to use. There are two main principles of OOCSS:
- Separation of structure and skin
- Separation of container and content
Separation of structure and skin
Structure is the basic core element which is invisible. These are the recurring elements that make up various page layouts and are not expected to change significantly over time. This includes properties such as width
, height
, padding
, margin
, overflow
, etc.
Picture from presentation “What is Object Oriented CSS?”
Skin is a decorative part and it’s about everything related to the brand of the site. It is bits and pieces that make your website different from the competition. You can think about properties like colors, borders, typography, shadows, gradients etc.
Skin, on the other hand, is the decorative part and it’s about everything related to the website’s brand. These are the little things that set your website apart from the competition. This includes properties like color
, border
, font-size
, box-shadow
, background
, etc.
Picture from presentation “What is Object Oriented CSS?”
Take a look at the following CSS and focus on repeating styles.
.button-primary {
/* Repeating styles */
display: inline-block;
padding: 16px 32px;
margin-bottom: 0;
font-size: 18px;
line-height: 32px;
text-align: center;
cursor: pointer;
/* Decorative part */
color: white;
background: black;
border: 0;
}
.button-secondary {
/* Repeating styles */
display: inline-block;
padding: 16px 32px;
margin-bottom: 0;
font-size: 18px;
line-height: 32px;
text-align: center;
cursor: pointer;
/* Decorative part */
color: black;
background: white;
border: 1px solid black;
}
We can use the following HTML for this stylesheet.
<button class="button-primary">Button</button>
<button class="button-secondary">Button</button>
In this example, we are styling two buttons. If you look at the code carefully, you will notice a significant amount of repetition. This can clutter your stylesheet over time and lead to potential inconsistencies.
Based on the concept of OOCSS, you can abstract the above CSS into structures and skins.
By separating them, we can reuse the classes and change their appearance by using another class for skin. Here is the refactored CSS according to the OOCSS principle.
/* Repeating styles for button */
.button {
display: inline-block;
padding: 16px 32px;
margin-bottom: 0;
font-size: 18px;
line-height: 32px;
text-align: center;
cursor: pointer;
}
/* Decorative parts - visual variants */
.button-primary {
color: white;
background: black;
border: 0;
}
.button-secondary {
color: black;
background: white;
border: 1px solid black;
}
Then we can use the following HTML (notice how classes are used to change the appearance).
<button class="button button-primary">Button</button>
<button class="button button-secondary">Button</button>
This way, we can save code, use modularity, and easily create other variants. If we decide to increase the font-size
of the button
, we can do it in one place and change all the buttons at once.
Separation of container and content
We should avoid writing styles that are location-dependent. The main motivation is that objects should look the same regardless of their location.
Content refers to objects such as media, images, paragraphs, which are nested inside other elements that serve as containers.
Styles used for content objects (elements) should be independent of the container class, allowing them to be used independently of their parent objects (elements). Take a look at the following example.
.widget {
/* foo */
}
.widget .list {
/* foo */
}
.widget .list .title {
/* foo */
}
.widget .list .content {
/* foo */
}
Now, let’s separate the content from the container.
.widget {
/* foo */
}
.list {
/* foo */
}
.list-title {
/* foo */
}
.list-content {
/* foo */
}
Now these classes can be used in many situations without the restriction of having a parent with the class .widget
or .list
. Learning how to use this principle may take some time, but the reward is the ability to write better code.
Takeaway
This method helps us think about styles in a more modular and object-oriented way. It also sets our mindset to write less repetitive code and helps us understand that extending selectors rarely leads to writing better code.
By trying to use or understand this methodology, you will gain a basic understanding of the issues related to the specificity and selectors structure, and you will understand how fragile CSS is. Is it a good thing?