<commit_before>---
layout: post
title: CSMess to OOCSS - Refactoring CSS With Object Oriented Design
---

[Presented at Fullstack Toronto Conf. 2016](https://eventmobi.com/fstoco2016/agenda/141857/806561)

## Slide deck

<iframe src="https://docs.google.com/presentation/d/12H2MLnGdaFN2xk-MRVyIRX4j77zQeAHytcUmFcQ6b2Q/embed?start=false&loop=false&delayms=5000" frameborder="0" width="560" height="344" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>

## How Object-Oriented Design Saved Our CSS (and Site Performance)

Back in January 2016, our CSS was easily the messiest part of the [Learn.co](https://learn.co) codebase… something that probably sounds familiar to many other web developers out there. Last spring, we budgeted time and resources to overhaul it. I led that project. Here's what we learned.

Before diving in, let’s clarify what we’re talking about when we talk about object-oriented design. Object-oriented code is:

- **Modular:** reusable
- **Encapsulated:** self-contained with minimal dependencies
- **Maintainable:** easy to work with, which is especially important for smaller dev teams like ours

[Learn.co](https://learn.co) is built on a Rails backend, and Rails strongly encourages writing code in an object-oriented paradigm. But how does object orientation apply to stylesheets? As good Rubyists, we tried to follow object orientation with our CSS, but we were doing it wrong. To illustrate, let’s take a look at our old stylesheets directory tree.

![Stylesheet Directory Tree]({{ site.baseurl }}/assets/css-tree.png "Stylesheet Directory Tree")

Very similar to the Rails boilerplate setup, we had one stylesheet per view, with styles namespaced under a top level ID. This approach is fine when you’re starting out, but over time, it can get out of hand. Just look at where ours was pre-rewrite:

![Stylesheet Directory Bundle]({{ site.baseurl }}/assets/css-bundle.png "Stylesheet Directory Bundle")

As you might be able to guess from this sizeable bundle, this approach is NOT object oriented.

**It’s not modular.** Styles are page-specific, so opportunities for code sharing are missed, and you end up with lots of code duplication. Plus, if you redefine styles on a page-by-page basis, you inevitably end up with inconsistencies in implementation and the visual interface itself.

**It’s not encapsulated.** Nesting everything under a top-level ID kicks things off with a high level of specificity that you’ll be battling throughout the rest of your stylesheets. This setup also makes it hard to predict what’ll happen when you change a class name or reorganize the sheet.

**It’s not maintainable.** Maintaining this kind of CSS is PAINFUL. Writing new CSS for every new view slows down development. It slows down page performance, too, contributing to a massive assets payload. Lots of new CSS means lots of churn, again increasing the risk of inconsistencies in code and design. And good luck trying to onboard into that mess.

We knew our CSS was broken. But what’s the solution?

Enter OOCSS.

![OOCSS]({{ site.baseurl }}/assets/briefcase.gif "OOCSS")

After consulting with our good pals at [Cantilever.co](http://cantilever.co/), we committed to an OOCSS solution. But now we had another decision to make: use an existing OOCSS framework or roll our own?

There are lots of off-the-shelf frameworks out there, including [Twitter Bootstrap](https://getbootstrap.com/2.3.2/), [Yahoo Pure](https://purecss.io/), and [Zurb Foundation](http://foundation.zurb.com/) (some of the most popular options). We considered three main factors.

**Performance.** Most off-the-shelf OOCSS frameworks are one-size-fits-all, aka HEAVY. We thought it’d be more efficient to roll our own framework, because we could limit it to the leanest, cleanest version possible.

**Adaptability.** Pre-rewrite, we relied on a good amount of vendor styles. Any time we needed to customize something, we’d create an “override” sheet, adding more payload and more specificity conflicts. So we loved the idea of sticking to easily-adaptable, in-house styles only.

**Speed of development.** With third party libraries, you have to wait for the maintainers to make updates and fix bugs, and their schedules don’t always align with yours. We ship fast, so being able to manage dependencies and handle updates internally was super appealing.

![OOCSS Options]({{ site.baseurl }}/assets/oocss-solution-table.png "OOCSS Options")

We had a big task in front of us: writing our own Learn.co-customized OOCSS framework. We broke the process out into a four step roadmap:

1. Take visual inventory of app’s UI/UX
2. Build component OOCSS library
3. Rewrite CSS and markup
4. Onboard the rest of the team


### STEP 1: VISUAL INVENTORY

The first thing you’ll want to do is take a visual inventory of your entire site. The goal is to break down the design into recognizable patterns. We can use the [Learn.co](https://learn.co) landing page as an example.

![Learn.co homepage]({{ site.baseurl }}/assets/learn-co-homepage.png "Learn.co homepage")

Start with the base layout - your header, footer, sidebar, etc.

![Learn.co layout scope]({{ site.baseurl }}/assets/learn-layout-scope.png "Learn.co layout scope")

Then take one step inward and look for “containers”. Look inside those containers for recurring “objects”.

![Learn.co container scope]({{ site.baseurl }}/assets/learn-container-scope.png "Learn.co container scope")


### STEP 2: COMPONENT LIBRARY

After you’ve identified repeating patterns, the next step is to translate them into CSS. Working with [Cantilever.co](http://cantilever.co/), we designed a system that groups stylesheets into four main scopes:

**Layout components** set the baseline styles for the page grid, headers, footers, overlays, etc. Since these classes require the most precision and are the least likely to change, they tend to contain more rigid, powerful rules than the rest of your components.

![Layout Components]({{ site.baseurl }}/assets/layout-components.png "Layout Components")

**Container components** are the real workhorse of your OOCSS system. They’re built to contain other elements, like lists or images, and they’re in charge of handling spacing, background, borders, and alignment.

![Container Components]({{ site.baseurl }}/assets/container-components.png "Container Components")

**Object components** handle styles for the smallest, discrete elements at the very bottom of the DOM tree, like buttons, links and images. They’re always the containee, not the container, and they should have the same, predictable behavior no matter what container they’re placed inside.

![Object Components]({{ site.baseurl }}/assets/object-components.png "Object Components")

**Global components** are your cleanup classes, little helpers that allow you to make precision adjustments. Examples include display utilities that hide/show elements at certain breakpoints. These should be applied sparingly to prevent inconsistencies in implementation and/or UX.

![Global Components]({{ site.baseurl }}/assets/global-components.png "Global Components")

Now our stylesheets directory looks something like this:

```
└── assets
      └── stylesheets
          ├── layout
          │   ├── site-header.scss
          │   ├── site-footer.scss
          │   └── site-main.scss
          ├── containers
          │   ├── list.scss
          │   ├── media-block.scss
          │   └── module.scss
          ├── objects
          │   ├── button.scss
          │   ├── image-frame.scss
          │   └── input.scss
          ├── global
          │   ├── special.scss
          │   ├── typography.scss
          │   └── vars.scss
          └── application.scss
```

When it comes to actually writing the CSS, you’ll want to focus on writing modular components defined through strong naming conventions.

**Modular components** are compartmentalized. Individual classes should do small things. Combine these small classes to get the big, complex looks you want. They should also be portable; our container and object elements should fit neatly into any column width. Your end goal should be to have a system where you can grab a block of markup from one template and drop it into another with complete confidence in what the end result will look like.

**Strong naming conventions** provide structure. CSS gives you so much freedom when it comes to naming things, so it’s important to develop a shared semantic syntax for your class names. Your devs should be able to glance at a class name and have a reasonable idea of what the element looks like on the page. You’ll want to use abstract, generic class names. Don’t base names on a specific location or use-case. Instead, class names should reference their visual role. For example, `.homepage-project-list` is not so great, but `.bubble-list` is pretty good.

We chose [BEM syntax](https://en.bem.info/method/key-concepts/) for our system, which gives us self-documenting class names that are accurate and clear, if a little verbose.

BEM stands for "Block-Element-Modifier":

```scss
/* Block component */
.list

/* Child element of parent block */
.list__card

/* Modifier that changes the style of the block */
.list--accordion
.list--spacing-large

```

When you use BEM naming conventions for CSS, think of your class names like objects. Apply the root namespace to the parent element - in the above example, an unordered list `<ul>`. Child elements are designated by the double underscore, and any modifiers are indicated with a double dash. Note that we’re not nesting any of these classes; there’s no need, since we can read the relationship between objects from the name itself. Plus this way, we avoid any specificity battles because everything’s on the same level.<commit_msg>add img<commit_after>---
layout: post
title: CSMess to OOCSS - Refactoring CSS With Object Oriented Design
---

[Presented at Fullstack Toronto Conf. 2016](https://eventmobi.com/fstoco2016/agenda/141857/806561)

## Slide deck

<iframe src="https://docs.google.com/presentation/d/12H2MLnGdaFN2xk-MRVyIRX4j77zQeAHytcUmFcQ6b2Q/embed?start=false&loop=false&delayms=5000" frameborder="0" width="560" height="344" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>

## How Object-Oriented Design Saved Our CSS (and Site Performance)

Back in January 2016, our CSS was easily the messiest part of the [Learn.co](https://learn.co) codebase… something that probably sounds familiar to many other web developers out there. Last spring, we budgeted time and resources to overhaul it. I led that project. Here's what we learned.

Before diving in, let’s clarify what we’re talking about when we talk about object-oriented design. Object-oriented code is:

- **Modular:** reusable
- **Encapsulated:** self-contained with minimal dependencies
- **Maintainable:** easy to work with, which is especially important for smaller dev teams like ours

[Learn.co](https://learn.co) is built on a Rails backend, and Rails strongly encourages writing code in an object-oriented paradigm. But how does object orientation apply to stylesheets? As good Rubyists, we tried to follow object orientation with our CSS, but we were doing it wrong. To illustrate, let’s take a look at our old stylesheets directory tree.

![Stylesheet Directory Tree]({{ site.baseurl }}/assets/css-tree.png "Stylesheet Directory Tree")

Very similar to the Rails boilerplate setup, we had one stylesheet per view, with styles namespaced under a top level ID. This approach is fine when you’re starting out, but over time, it can get out of hand. Just look at where ours was pre-rewrite:

![Stylesheet Directory Bundle]({{ site.baseurl }}/assets/css-bundle.png "Stylesheet Directory Bundle")

As you might be able to guess from this sizeable bundle, this approach is NOT object oriented.

**It’s not modular.** Styles are page-specific, so opportunities for code sharing are missed, and you end up with lots of code duplication. Plus, if you redefine styles on a page-by-page basis, you inevitably end up with inconsistencies in implementation and the visual interface itself.

**It’s not encapsulated.** Nesting everything under a top-level ID kicks things off with a high level of specificity that you’ll be battling throughout the rest of your stylesheets. This setup also makes it hard to predict what’ll happen when you change a class name or reorganize the sheet.

**It’s not maintainable.** Maintaining this kind of CSS is PAINFUL. Writing new CSS for every new view slows down development. It slows down page performance, too, contributing to a massive assets payload. Lots of new CSS means lots of churn, again increasing the risk of inconsistencies in code and design. And good luck trying to onboard into that mess.

We knew our CSS was broken. But what’s the solution?

Enter OOCSS.

![OOCSS]({{ site.baseurl }}/assets/briefcase.gif "OOCSS")

After consulting with our good pals at [Cantilever.co](http://cantilever.co/), we committed to an OOCSS solution. But now we had another decision to make: use an existing OOCSS framework or roll our own?

There are lots of off-the-shelf frameworks out there, including [Twitter Bootstrap](https://getbootstrap.com/2.3.2/), [Yahoo Pure](https://purecss.io/), and [Zurb Foundation](http://foundation.zurb.com/) (some of the most popular options). We considered three main factors.

**Performance.** Most off-the-shelf OOCSS frameworks are one-size-fits-all, aka HEAVY. We thought it’d be more efficient to roll our own framework, because we could limit it to the leanest, cleanest version possible.

**Adaptability.** Pre-rewrite, we relied on a good amount of vendor styles. Any time we needed to customize something, we’d create an “override” sheet, adding more payload and more specificity conflicts. So we loved the idea of sticking to easily-adaptable, in-house styles only.

**Speed of development.** With third party libraries, you have to wait for the maintainers to make updates and fix bugs, and their schedules don’t always align with yours. We ship fast, so being able to manage dependencies and handle updates internally was super appealing.

![OOCSS Options]({{ site.baseurl }}/assets/oocss-solution-table.png "OOCSS Options")

We had a big task in front of us: writing our own Learn.co-customized OOCSS framework. We broke the process out into a four step roadmap:

1. Take visual inventory of app’s UI/UX
2. Build component OOCSS library
3. Rewrite CSS and markup
4. Onboard the rest of the team


### STEP 1: VISUAL INVENTORY

The first thing you’ll want to do is take a visual inventory of your entire site. The goal is to break down the design into recognizable patterns. We can use the [Learn.co](https://learn.co) landing page as an example.

![Learn.co homepage]({{ site.baseurl }}/assets/learn-co-homepage.png "Learn.co homepage")

Start with the base layout - your header, footer, sidebar, etc.

![Learn.co layout scope]({{ site.baseurl }}/assets/learn-layout-scope.png "Learn.co layout scope")

Then take one step inward and look for “containers”.

![Learn.co container scope]({{ site.baseurl }}/assets/learn-container-scope.png "Learn.co container scope")

Look inside those containers for recurring “objects”.

![Learn.co object scope]({{ site.baseurl }}/assets/learn-object-scope.png "Learn.co object scope")


### STEP 2: COMPONENT LIBRARY

After you’ve identified repeating patterns, the next step is to translate them into CSS. Working with [Cantilever.co](http://cantilever.co/), we designed a system that groups stylesheets into four main scopes:

**Layout components** set the baseline styles for the page grid, headers, footers, overlays, etc. Since these classes require the most precision and are the least likely to change, they tend to contain more rigid, powerful rules than the rest of your components.

![Layout Components]({{ site.baseurl }}/assets/layout-components.png "Layout Components")

**Container components** are the real workhorse of your OOCSS system. They’re built to contain other elements, like lists or images, and they’re in charge of handling spacing, background, borders, and alignment.

![Container Components]({{ site.baseurl }}/assets/container-components.png "Container Components")

**Object components** handle styles for the smallest, discrete elements at the very bottom of the DOM tree, like buttons, links and images. They’re always the containee, not the container, and they should have the same, predictable behavior no matter what container they’re placed inside.

![Object Components]({{ site.baseurl }}/assets/object-components.png "Object Components")

**Global components** are your cleanup classes, little helpers that allow you to make precision adjustments. Examples include display utilities that hide/show elements at certain breakpoints. These should be applied sparingly to prevent inconsistencies in implementation and/or UX.

![Global Components]({{ site.baseurl }}/assets/global-components.png "Global Components")

Now our stylesheets directory looks something like this:

```
└── assets
      └── stylesheets
          ├── layout
          │   ├── site-header.scss
          │   ├── site-footer.scss
          │   └── site-main.scss
          ├── containers
          │   ├── list.scss
          │   ├── media-block.scss
          │   └── module.scss
          ├── objects
          │   ├── button.scss
          │   ├── image-frame.scss
          │   └── input.scss
          ├── global
          │   ├── special.scss
          │   ├── typography.scss
          │   └── vars.scss
          └── application.scss
```

When it comes to actually writing the CSS, you’ll want to focus on writing modular components defined through strong naming conventions.

**Modular components** are compartmentalized. Individual classes should do small things. Combine these small classes to get the big, complex looks you want. They should also be portable; our container and object elements should fit neatly into any column width. Your end goal should be to have a system where you can grab a block of markup from one template and drop it into another with complete confidence in what the end result will look like.

**Strong naming conventions** provide structure. CSS gives you so much freedom when it comes to naming things, so it’s important to develop a shared semantic syntax for your class names. Your devs should be able to glance at a class name and have a reasonable idea of what the element looks like on the page. You’ll want to use abstract, generic class names. Don’t base names on a specific location or use-case. Instead, class names should reference their visual role. For example, `.homepage-project-list` is not so great, but `.bubble-list` is pretty good.

We chose [BEM syntax](https://en.bem.info/method/key-concepts/) for our system, which gives us self-documenting class names that are accurate and clear, if a little verbose.

BEM stands for "Block-Element-Modifier":

```scss
/* Block component */
.list {}

/* Child element of parent block */
.list__card {}

/* Modifier that changes the style of the block */
.list--accordion {}
.list--spacing-large {}

```

When you use BEM naming conventions for CSS, think of your class names like objects. Apply the root namespace to the parent element - in the above example, an unordered list `<ul>`. Child elements are designated by the double underscore, and any modifiers are indicated with a double dash. Note that we’re not nesting any of these classes; there’s no need, since we can read the relationship between objects from the name itself. Plus this way, we avoid any specificity battles because everything’s on the same level.
{'fraction_non_alphanumeric': 0.08124271451016167, 'fraction_numerical': 0.005372256854695657, 'mean_word_length': 4.1844456121912765, 'pattern_counts': {'":': 2, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 16, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2144894', 'n_tokens_mistral': 5410, 'n_tokens_neox': 5124, 'n_words': 2668}