CSS Methodologies Roundup

CSS is notoriously difficult to manage in large, complex, rapidly-iterated systems.

One reason is that CSS lacks a built-in scoping mechanism. Everything in CSS is global. That means any change you make has the potential to cascade and alter the presentation of unrelated bits of the UI.

Extended CSS languages (otherwise known as CSS preprocessors) such as Sass, Less and Stylus make things a little easier by offering up features that make writing CSS easier. But even these solutions don't truly fix CSS's scalability issue.

Until CSS gets its own native scoping mechanism, we need to devise our own system for locking down styles to specific sections of an HTML document.

CSS methodologies are the solution.

CSS methodologies are formal, documented systems for authoring CSS in a way that allows us to develop, maintain and scale the front-end as a set of small, isolated modules rather than as one massive lump of indivisible code.

In this article, I take a look at these CSS methodologies:

  • Object-Oriented CSS (OOCSS)
  • Block, Element, Modifier (BEM)
  • Scalable and Modular Architecture for CSS (SMACSS)
  • SUIT CSS

Plus I explain the methodology that I deploy in my own projects to keep CSS manageable at scale.

Each CSS methodology offers a slightly different set of solutions to the CSS scalability/maintainability problem. A CSS methodology will often define guidelines for:

  • CSS and HTML best practices
  • Naming conventions
  • Ordering and grouping of CSS style rules
  • Code formatting

There is no "best" CSS methodology. Different approaches work better for different individuals/teams/projects.

Hopefully, looking at a few existing CSS methodologies will help you discover one that fits your needs. Or it might inspire you to create your own custom CSS-authoring guidelines.

Adopting a CSS methodology — even if it's one that you create yourself — will make it easier for you to design and iterate on your web design projects, regardless of scale and complexity.

Object-Oriented CSS (OOCSS)

Nicole Sullivan's Object-Oriented CSS, or OOCSS for short, was published in 2009.

It was the first CSS methodology to become widely adopted. It's still hugely influential today.

OOCSS advocates the separation of structure from skin. The methodology makes a clear distinction between content and its containers.

In OOCSS, style rules are written exclusively using CSS class selectors.

For example, the style of button elements might be set via two classes: button and grey-btn:

  • .button provides the button's basic structure
  • .grey-btn applies colors and other visual properties
.button {
    box-sizing: border-box;
    height: 50px;
    width: 100%;
}

.grey-btn {
    background: #EEE;
    border: 1px solid #DDD;
    box-shadow: rgba(0, 0, 0, 0.5) 1px 1px 3px;
    color: #555;
}

One goal of the OOCSS methodology is to reduce duplication of the same properties throughout your various style rules. In other words, OOCSS can help us maintain DRY stylesheets. The methodology attempts to achieve this goal by using lots of small, modular, specialist CSS classes.

Very few style properties are applied via type selectors (e.g. h1, div and body).

The use of descendant selectors is discouraged, too.

.wrapper .blog-post .button {
    //...
}

This way, the presentation of HTML elements is never dependent upon them being used in a specific context or DOM structure.

The great thing about the OOCSS methodology is it urges authors to make the most of CSS's cascading behavior, rather than trying to lock it up with high-specificity selectors.

Authors are encouraged, whenever possible, to reuse existing style rules instead of creating new ones. We are also encouraged to extend style rules by specifying additional CSS properties with new classes, rather than modifying or overwriting existing CSS properties.

The main downside of OOCSS is that you can end up with an awful lot of classes. Which can be difficult to maintain and manage.

And the concept of object-oriented programming — which is where OOCSS takes inspiration from — does not fit comfortably with CSS.

But that's not to say the principles of OOCSS are invalid. On the contrary, OOCSS is a commonsense CSS methodology that brings back sanity to large-scale CSS development.

Block, Element, Modifier (BEM)

Block, Element, Modifier — more commonly called BEM — is a CSS class-naming system devised by the dev team at Yandex (the Google of Russia).

The idea behind BEM is to differentiate CSS classes that fulfill different roles. This is done by naming CSS classes in a way that indicates their role.

BEM complements OOCSS because OOCSS doesn't impose any particular class-naming convention.

In BEM terminology, a block is an independent, modular UI component. A block may be composed of multiple HTML elements, or even multiple blocks. An example of a block might be your navigation menu or search form.

An element is a component of a block. An element serves a singular purpose. For example, if you have a navigation menu block, then elements of it might be your navigation menu's links, which in turn might be in the form of list items (<li> elements) and links (<a> elements).

A modifier is a CSS class that changes the default presentation of a block or element.

This is the BEM class-naming syntax:

.block
.block--modifier
.block__element
.block__element--modifier

Consider the following example, the markup for a login form:

<form>
    <label>Username <input type="text" name="username" /></label>
    <label>Password <input type="password" name="password" /></label>
   <button>Sign in</button>
</form>

Here's the markup above with BEM classes applied:

<form class="loginform loginform--errors">
    <label class="loginform__username loginform__username--error">
        Username <input type="text" name="username" />
    </label>
    <label class="loginform__password">
        Password <input type="password" name="password" />
    </label>
    <button class="loginform__btn loginform__btn--inactive">
        Sign in
    </button>
</form>

The .loginform class is the block. It is composed of three elements:

  • .loginform__username: username input field
  • .loginform__password: password input field
  • .loginform__btn: form submission button

The three modifiers are:

  • .loginform__username--error: when there's an error, the element's visual properties are modified so that it indicates to the user there was an error
  • .loginform__btn--inactive: the element's visual properties are modified so that it has an inactive appearance
  • .loginform--errors: this modifier visually presents the login form in a manner indicating that it contains errors

The BEM naming convention helps CSS authors comply with the OOCSS principle of using a flat selector hierarchy composed of equally-specific class selectors. It also helps OOCSS authors avoid deep descendant selectors.

So instead of the following style rule, which uses three CSS class selectors...

.loginform .username .error {
    //...
}

... you can just use a single class selector:

.loginform__username--error {
    //...
}

BEM is a very robust class-naming convention.

It successfully distinguishes the different concerns that classes are used for. And it's easy to see in the markup which classes are related to one another.

A couple of subjective criticisms against BEM are:

  • The class names can end up being long and ugly.
  • The naming convention is not intuitive to inexperienced developers.

Personally, I don't think those are particularly strong criticisms. However, it would be nice to have a class-naming convention that is as robust as BEM, while also being a little tidier and more intuitive.

Scalable and Modular Architecture for CSS (SMACSS)

Jonathan Snook published his book on Scalable and Modular Architecture for CSS in 2011. It is abbreviated as SMACSS and pronounced as "smacks".

A key idea in this CSS methodology is how we categorize our CSS style rules.

Snook came up with five categories:

  • Base styles
  • Layout
  • Modules
  • State
  • Themes

Base styles set the default CSS properties of individual HTML elements. These are typically CSS type selectors. Examples:

h1 {
   font-size: 32px;
}

div {
    margin: 0 auto;
}

a {
    color: blue;
}

Layout rules are related to the structural layout of web pages: containers, the grid, etc. They are prefixed with layout- or l-. Examples:

.layout-sidebar {
    width: 320px;
}

.l-comments {
    width: 640px;
}

Modules are style rules that format modular, reusable components. Examples:

.call-to-action-button {
    text-transform: uppercase;
    color: #FFF200;
}

.search-form {
    display: inline-block;
    background-color: #E1E1E1;
}

State rules are dedicated to specifying the current state of something in the interface. Examples:

.is-hidden {
    display: none;
}

.is-highlighted {
    color: #FF0000;
    background-color: #F4F0BB;
    border: 1px solid #CBBD15;
}

Finally, themes are style rules that affect layout and modules and are triggered by user preferences/actions/viewing contexts.

SMACSS offers a simpler naming convention than BEM. There are no names for base styles because only type selectors (h1, p, a, etc.) are used for those. Modules are given their own unique class names. Sub-components and variations are prefixed with the name of their parent module.

Let's say our layout container is called .l-footer. We have a search form module inside it. The search form has already been submitted at least once by the user. This might be our markup:

<section class="l-footer">
    <form class="search is-submitted">
        <input type="search" />
        <input type="button" value="Search">
    </form>
</section>

SMACSS discourages the use of descendant selectors. Jonathan Snook explains this by introducing a concept he calls depth of applicability. This concept is all about limiting the impact that CSS has on HTML markup by using classes to very precisely target elements you want to style.

SUIT CSS

Nicolas Gallagher's SUIT CSS, introduced in 2014, is interesting because it combines a BEM-like class-naming system with a CSS preprocessor. So SUIT CSS provides us with extended CSS syntax a la Sass, Less or Stylus.

SUIT CSS classes come in five formats:

  • u-utilityName
  • ComponentName
  • ComponentName--modifierName
  • ComponentName-elementName
  • ComponentName.is-stateOfName

This class-naming convention highlights the division between:

  • General utility classes
  • Standalone/modular UI components
  • Individual elements
  • Modifiers

Here's how this CSS methodology might get applied to a login form:

<form class="LoginForm LoginForm--errors">
    <label class="LoginForm-username is-required">
        Username <input type="text" name="username" />
    </label>
    <label class="LoginForm-password">
        Password <input type="password" name="password" />
    </label>
    <button class="LoginForm-button is-inactive">Sign in</button>
</form>

My CSS methodology

My own methodology for managing CSS at scale shares many of the principles and ideas you can find in OOCSS, BEM, SMACSS, SUIT CSS, and other CSS methodologies. But it is intended to be simpler. There are fewer rules to remember, and the class-naming convention is more intuitive.

The process of developing a new web design is broken up into four phases:

  • Layout
  • Elements
  • Widgets
  • Modifiers

First, an empty wireframe-like layout is created from a series of sectioning elements such as <section> and <div>:

<div class="CONTAINER">
    <header class="BANNER"></header>
    <nav class="NAVIGATION_PRIMARY"></nav>
    <nav class="NAVIGATION_SECONDARY"></nav>
    <main class="MAIN"></main>
    <aside class="ADVERTS"></aside>
    <footer class="FOOTER">
        <nav class="SITEMAP"></nav>
        <div class="LEGAL"></div>
    </footer>
</div>

Second, we establish the default presentation for HTML elements that will encapsulate content and render interactive controls. Examples include headings (h1, h2, h3), paragraphs (p), lists (ul and ol), tables, forms, and so forth.

Third, we identify recurring patterns of content in our designs. We bundle these recurring patterns up into independent modules of markup and styling (and scripting if needed).

These bundles of recurring content patterns I like to call UI "widgets". For example, here's the markup for two widgets that render a navigation bar and search form:

<div class="NavBar">
    <ul>
        <li><a href="./">Home</a></li>
        <li><a href="about.html">About</a></li>
        <li><a href="learn/">Learn</a></li>
        <li><a href="extend/">Extend</a></li>
        <li><a href="share/">Share</a></li>
    </ul>
</div>

<div class="SearchBox">
    <form action="search.html" method="get">
        <label for="input-search">Search</label>
        <input name="q" type="search" id="input-search" />
        <button type="submit">Search</button>
    </form>
</div>

Content — in the form of widgets and naked HTML elements — is then placed within the layout.

Finally, modifier classes are added to vary the default presentation of things.

In the following example the navbar-primary modifier varies the default presentation of the NavBar widget, and the navbar-selected modifier targets the current selection:

<div class="NavBar navbar-primary">
    <ul>
        <li><a href="./">Home</a></li>
        <li><a href="about.html" class="navbar-selected">About</a></li>
        <li><a href="learn/">Learn</a></li>
        <li><a href="extend/">Extend</a></li>
        <li><a href="share/">Share</a></li>
    </ul>
</div>

In this methodology, each class performs one, and only one, of the following roles:

  • It represents the name of a layout section
  • It represents the namespace for a widget
  • It modifies the default presentation of something

The three types of classes adopt different naming conventions, to easily tell them apart.

  • Layout: UPPER_CASE
  • Widget: CamelCase
  • Modifier: lower_case

What's nice about this naming convention is the hierarchy of classes is represented by their letter-casing.

Layout classes, written using all-upper-case letters, scream out from the markup. Examples: NAVIGATION, SIDEBAR, FOOTER.

The CamelCase letter-casing of widgets, which will always be nested within layout classes, are a little less prominent. Examples: MainMenu, ImageGrid, BlogPost.

Modifier classes — which are arguably the least important classes since they merely modify things and are not critical to achieving a default presentation — are the least conspicuous of all, being written in all-lower-case letters. Examples: is-highlighted, has-errors, hidden.

Conclusion

All CSS methodologies tackle the scalability and maintainability problem in CSS by providing a class-based system for breaking up big web designs into lots of small, modular, discrete units. Each UI module can be reused over and over throughout a design, and even ported from one project to another if two projects share the same CSS methodology.

In the process, CSS methodologies do much more than fix the CSS scalability problem. They make it easier to develop and iterate a design. They make front-end code easier to read and understand, provide ready-made documentation, and make it easier for multiple people to collaborate on a design.

Adopting a CSS methodology can reduce the learning curve for new designers joining a project, and make for a smoother transition when a project is handed over to a new team.

And because CSS methodologies encourage reuse of existing code, they enforce consistency in visual designs and reduce page size and increase page rendering speed.

CSS methodologies have different class-naming conventions and they carve up web designs along slightly different lines. But the specifics of any particular methodology are less important than the general solutions they provide for modularizing front-end code and making CSS easier to scale.

You can take away the ideas and develop your own categories of classes and devise your own class-naming conventions that work best for you. That's what I do. Treat the well-known CSS methodologies as a starting point, but every project is different, and I always tweak and extend my CSS methodology to better fit the skill set and creative temperament of the team I'm working with.

Other CSS Methodologies

  • Atomic Design: a design system that uses chemistry terms and analogies (atoms, molecules, and organisms).
  • DoCSSa: a Sass-based CSS methodology by Matthieu Larcher and Fabien Zibi. (offline)
  • csstyle: a Sass/PostCSS-based methodology by Dave Geddes.