Writing SCSS with BEM

Day to day, I read and write a quite a lot of SCSS. I often follow BEM’s guidelines whilst writing it. So naturally over time I’ve developed opinions on what I think concise, clear but also maintainable BEM + SCSS looks like.

The Ideal Example #

So below is how, in an ideal world, I would write SCSS:

.block {
  &__element {
    &:hover {
      ...
    }

    @media screen and (min-width: 768px) {
      ...
    }

    &--modifier {
      &:hover {
        ...
      }

      @media screen and (min-width: 768px) {
        ...
      }
    }
  }

  &__element-sibling {
    ...
  }
}

There’s a few things going on above so let’s break it down.

Use the & alias to keep BEM concise #

So one of the main nuisances with BEM is it’s tendancy to produce looooong class names e.g .navigation-bar__hero-title--highlighted. So to remedy this in your stylesheets, I find it a good idea to break up the name through a combination of nesting and the SCSS & alias.

For those unfamiliar, the & alias is shorthand for the parent selector that the & is nested in. For example…

.button {
  &__icon {
    ...
  }
}

…when compiled down to CSS will be .button__icon. A lot less duplication with all the safety and niceness of BEM.

It also has the added bonus that styles that use & get compiled into single class styles i.e. .button__icon vs. .button .button__icon. This is good because it keeps the specificity low and the styles open to being overriden.

However, the & alias can be painful. Imagine the scenario where a set of styles were misbehaving. A developer would open up the browser dev tools, find the offending class name and do a file search for it in their codebase. If the selector is broken up using & aliases then searching for .button__icon like in the example above won’t produce any results.

This issue can be aleviated however by following some simple rules…

Use nesting to reflect the BEM hierarchy #

So I usually have three levels of style nesting:

Each corresponds to levels of the BEM hierarchy. So it would look something like:

.block {
  &__element {
    &--modifier {
      ...
    }
  }
}

Nested inside each of these levels may be media queries and pseudo-class rules, bringing the max level of nesting to four (e.g. a media query in a modifier class).

If your stylesheets are consistently structured like this, then file searching for styles is easy.

For example, if you were trying to debug styles for .button__icon you could search for &__icon. Or if there are multiple occurrences of that, search for .button and then locate the &__icon nested inside of it.

Don’t abuse nesting #

Going from CSS to SCSS, you can get carried away with the cool features SCSS gives you. Over-nesting of styles is a particular headache of mine.

.class-1 {
  .class-2 {
    .class-3 {
      .class-4 {
        ...
      }
    }
  }
}

In this small example, it’s just about readable. But imagine a stylesheet that’s hundreds of lines long. If you need to add a style, it gets harder and harder to figure out what level of the nesting you’re adding to.

Also, if you’re not using the & alias, SCSS will compile the above styles to:

.class-1 .class-2 .class-3 .class-4 {
  ...
}

Each level of nesting bumps up the specificity of the styles and makes them harder and harder to override. 👎

Don’t nest similarly named classes #

Nesting blocks/elements/modifiers inside similarly named classes is a bit of a pet peeve of mine, it makes the nested classes much harder to find. Take the following example:

Do

.block {
  // .block__element
  &__element {
    ...
  }

  // .block__element-two
  &__element-two {
    ...
  }
}

Don't

.block {
  // .block__element
  &__element {
    // .block__element-two
    &-two {
      ...
    }
  }
}

By avoiding nesting .block__element-two inside .block__element we make both elements easy to search for and, in my opinion, we make the code more scannable.

For scoping, use modifiers over nesting #

In addition, nesting is often used to “scope” styles to specific contexts. But if you’re using BEM, you don’t need to worry about that. Prefixing the block name to all classes does the scoping for you.

If you need to slightly tweak a block on a specific page, I find it better to use modifier classes to adapt the block instead of changing the styles inside a page-specific class.

One block per file #

I find having one SCSS file per block a nice rule of thumb. It makes each block discoverable via file explorers and keeps each file small and concise.

Summary #

Next ›
Promoting CSS reuse