Organizing CSS: OOCSS, SMACSS, and BEM
!Warning: This post is over a year old. I don't always update old posts with new information, so some of this information may be out of date.
Eric Barnes, the author of Laravel News, mentioned in his newsletter this week that he's been looking for a better way to organize his CSS. He mentioned three methods he'd looked into: SMACSS, OOCSS, and BEM, and that he had seen me writing in BEM in the video I posted last week.
I wanted to clarify a little bit, and hope this could add a little to the conversation around well-architected, modular CSS: At Tighten we do use BEM... but we also use OOCSS. And SMACSS. At the same time.
I'd love to share why and how.
What is OOCSS?
OOCSS is a programming paradigm. OOCSS stands for Object Oriented CSS, so it's best understood in the context of Object Oriented programming: classic (spaghetti) CSS vs. OOCSS is a bit like procedural (spaghetti) backend code vs. Object-Oriented backend code.
OOCSS focuses on flexible, modular, swappable components that do One Thing Well. OOCSS focuses on the single responsibility principle, separation of concerns, and much more of the foundational concepts of Object Oriented Programming.
For a great introduction to OOCSS, this post on the OOCSS Media Object (written by the/one of the people behind OOCSS) shows an example of what a CSS object looks like, and some of the benefits of using one.
Here's a sample, from that post, of an OOCSS object:
.media {}
.media .img {}
.media .img img {}
.media .imgExt {}
.bd {}
As you can see, .media
is an object, and the goal is to make that object independent of its surroundings so that it can be placed anywhere in your site.
What is SMACSS?
SMACSS stands for Scalable and Modular Architecture for CSS. It's a book and a methodology for writing CSS (created by Jonathan Snook), but its most significant and influential aspect is its organizational system, which is designed to provide a set of buckets into which CSS should be organized. To learn more, check out the SMACSS web site and read or order the book there.
What is BEM?
BEM is a specific concrete application of OOCSS. BEM stands for Block Element Modifier, and it describes the pattern of each CSS object's class name. We use a modified form of BEM, described best by CSS Wizardry's post titled MindBEMding.
Essentially, each BEM class starts with a block, which is an object name. Let's start with .byline
. Then, for children of that block, you add an element, separating it with two underscores: .byline__name
. Finally, you can modify any class (block or element) by adding a modifier, separated with two hyphens: .byline--expanded
.
.byline {}
.byline__name {}
.byline__title {}
.byline__picture {}
.byline--expanded {}
.byline--expanded__bio {}
Here's the OOCSS media object in BEM syntax:
.media {}
.media__img {}
.media__img--rev {}
.media__body {}
This post isn't the best place to describe the merits of BEM, but a few quick benefits: modularity, a shallow selector structure, and a much decreased likeliness of class name overlap are some of the biggest benefits of using BEM.
How does Tighten use all three?
Since OOCSS is an abstract coding methodology, BEM is a concrete application of OOCSS, and SMACSS is an OOCSS-focused organizational structure, they actually play together very nicely--especially when you throw Sass into the mix.
Each of our applications have a core style.scss
file, which includes several partials. We use a SMACSS-inspired organizational structure, so we'll usually end up with a few basic files:
style.scss
Core file: imports the others.
_base.scss
Includes normalize.css
, and also sets styles on base elements: html
, body
, a
, ul
, li
, etc.
_layout.scss
Depending on the complexity of the site, we will likely have a file dedicated to layout. Grids, responsive frameworks, wrappers, etc. all live here.
_modules.scss
Includes definitions for our modules, or objects. The goal is for as much code to exist in here as possible, making it flexible and reusable. This file will just be a list of modules defined (and documented) one after another.
_other.scss
The name for this partial varies, but essentially this is all the code that doesn't fit in _base
, _layout
, or _modules
. Code we just couldn't make modular; glue between modules; top level layouts; etc.
_shame.scss
Also from CSS Wizardry (see CSS Wizardry's post on shame.css), a _shame
file is something we've been trying out only recently. This file is a place where you put all the code you're not proud of, with the intention of A) isolating it and B) fixing it later. The goal is for this file to be empty, but some times you just have to throw that hack in there to get it working.
We may also add a _javascript.scss
if we're not using Gulp or Grunt to concatenate the styles for our Javascript plugins.
Using BEM in Sass
In the past, a lot of the benefits of nesting with Sass was lost when you switched to BEM:
/* Sass pre-BEM: */
.object {
color: red;
.descendant {
color: black;
}
}
/* Generates:
.object {
color: red;
}
.object .descendant {
color: black;
}
*/
/* Sass with BEM: */
.object {
color: red;
}
.object__descendant {
color: black;
}
/* Generates:
.object {
color: red;
}
.object__descendant {
color: black
}
*/
But with Sass 3.3, we can finally get Sass nesting with BEM modules using the & to prefix our elements or modifiers:
/* Sass 3.3+ w/BEM: */
.object {
color: red;
&__descendant {
color: black;
}
}
/* Generates:
.object {
color: red;
}
.object__descendant {
color: black
}
*/
Hitimisho
As you can see, OOCSS, SMACSS, and BEM can play together nicely. And, as a result, we start to see a lot of the benefits of Object Orientation come to fruition in even our frontend code. It's a beautiful thing.
Do you have tips, tricks, or corrections? Let me know on Twitter at @stauffermatt.
Comments? I'm @stauffermatt on Twitter
Tags: css • bem • oocss • smacss • frontend • sass