BEM flavored SASS/SCSS Variable Names

Florian Heinze28.05.2018

Let's be honest, we all know this joke:

There are only two hard things in Computer Science: cache invalidation and naming things.
-- Phil Karlton

And that's bugging us too. Most of our projects are done using the Atomic Design Pattern to structure our components into atoms, molecules and organisms. For implementing and structuring components and their subparts we use BEM in combination with SCSS.

In the beginning the varibable names that we used felt rather arbitrary. They also changed between projects, which made it harder to onboard other developers. When looking back at older projects I sometimes do not remember why I chose a certain naming scheme.

This is when I realized that we need a well articulated naming scheme. 

Creating good names is hard, but it should be hard, because a great name captures essential meaning in just one or two words
Jeff Atwood

After quite some pondering I ended up with a naming scheme that solves the following problems:

1. Generalizing different naming schemes

2. Difficult recognition of variables in the autocompletion of my IDE

3. Refactoring of component names is not much fun

Improving your SASS variables naming with BEM

First let's start with a simple component following the BEM naming scheme.

<div class="button">...</div> <div class="button button--success">...</div> <div class="button button--disabled">...</div>

This might leave us with the following SCSS:

.button { background: grey; } .button--success { background: green; } .button--disabled { opacity: 0.5; }

Now we start introducing new variables for background and opacity:

$button__background: grey; $button--success__background: green; $button--disabled__opacity: 0.5; .button { background: $button__background; } .button--success { background: $button--success__background; } .button--disabled { opacity: $button--disabled__opacity; }

We concatenate the BEM class name "button--success" with the name of the property "background". The property can be the name of the CSS property, but in some cases it makes sense to choose a more semantical meaning

In the following example we change the variable naming from "...--background" to  "...--color", as we are now using the variable for different CSS properties.

$button__color: grey; $button--success__color: green; $button--disabled__opacity: 0.5; .button { border: 1px solid $button__color; background: $button__color; } .button--success { border: 1px solid $button--success__color; background: $button--success__color; } .button--hollow { background: none; } .button--disabled { opacity: $button--disabled__opacity; }

Adding semantics to your variables (e.g. by using "...--color" instead of "...--background") drastically helps others to better understand your code.

For the sake of naming a naming scheme, let me introduce you to $BEMP

Why I really enjoy using it

1. The autocompletion of my IDE is more fun to use, because variables have better semantics and are therefore easier to recognize.

KI generiert: Das Bild zeigt eine Programmierumgebung mit CSS/Sass-Code, in der Autovervollständigungen für eine CSS-Klasse namens ".button--success" vorgeschlagen werden. Der Hintergrund der Klasse wird mit einer Variable definiert.

2. Refactoring component names becomes so much easier, because we use the same naming scheme for component class names and variables.

Refactoring component names normally leads to ...

  • refactoring of HTML class attributes
  • refactoring of CSS class declarations
  • refactoring of SCSS variables

Usually the IDE support for this doesn't hit the point and takes quite some work to set up. The pragmatic approach would be search and replace, which naturally is easier when using  consistent naming.

E.g. we only need to replace "button--success" with "button--positive" and alle the variables will be changedcorrectly.

3. Onboarding new developers will be much faster with a well thought trough naming scheme.

But what about Global Variables?

Besides variables that are semantically tied to components we usually have some global variables, e.g. for typography, colors, spacings and sizes. For this I use "global" variables that have their own namespace and can be reused for the component specific variables.

I always have a _Variables.scss where all those variables can be found.

// Global Variables $base__size: 5px; $base__fontSize: 14px; $base__lineHeight: 1.6; $base__fontFamily: 'open_sansregular', 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; $base__touchSize: 36px; $spacing: 4 * $base__size; $spacing--big: 8*$base__size; $spacing--small: 2 * $base__size; $color__primary: red; $color__black: #000000; $color__white: #ffffff;

File structure - Where to place your variables

I normally use the Atomic Design Pattern which leads to the following structure:

  • App.scss​​​​​​
  • ​_Variables.scss
  • Atoms/
    • _Button.scss
    • _Link.scss
    • ...
  • Molecules/
    • _SearchBar.scss
    • ...
  • Organisms/
    • _Application.scss
    • _Sidebar.scss

I tried different approaches for structuring my variables, but for me it boils down to the following two: 

Approach A: Putting it all in one file (e.g. _Variables.scss)

I suggest using one SCSS file for each component (e.g. _Button.scss) for the components styling declarations, but keep all variables inside one file (e.g. _Variables.scss). This way you have all the variables that drive your styling in one place making it easier to allow e.g. theming.

// Global Variables $base__size: 5px; $base__fontSize: 14px; $base__lineHeight: 1.6; $base__fontFamily: 'open_sansregular', 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; $base__touchSize: 36px; $spacing: 4 * $base__size; $spacing--big: 8*$base__size; $spacing--small: 2 * $base__size; $color__primary: red; $color__black: #000000; $color__white: #ffffff; /* ... and more */ // Component Specific Variables $application__header__height: 116px; $stage__sidebar__width: 300px; $stage__header__height: 90px; $stage__content__maxWidth: 960px; $stage--scrollable__header__height: 140px;

This approach however makes it harder to reuse components. A way around this, would be to only use the component specific variables, move them to the SCSS of the component, e.g. the _Button.scss. This way you can directly see the styling API of your component.

Approach B:  Keep component specific variables in designated files

// _Button.scss $button__color: $color__primary; $button--success__color: $color__success; $button--disabled__opacity: 0.5; $button__fontFamily: $base__primaryFontStack; $button__borderRadius: $base__borderRadius; $button__innerSpacing: $base__size; .button { padding-left: $button__innerSpacing; padding-right: $button__innerSpacing; border: 1px solid $button__color; background: $button__color; font-family: $button__fontFamily border-radius: $button__borderRadius } .button--success { border: 1px solid $button--success__color; background: $button--success__color; } .button--disabled { opacity: $button--disabled__opacity; } .button--hollow { background: none; }

This approach might lead to problems for more complicated components (e.g. organisms), that cannot be completely separated because they need to share knowledge about their styling.

// _Sidebar.scss .sidebar { position: fixed; left: 0; top: 0; width: $sidebar__width; height: 100%; ... } // _Body.scss body { padding-left: $sidebar__width; ... }

In this example the body has to know about the width of the sidebar. This is why I would move the $sidebar__width to the _Variables.scss to show that it can be used by other components, leaving me with some component specific variables outside of their designated SCSS files, which does not really feel consistent.

This is why I decided to go with approach A, keeping component specific AND global variables inside the _Variables.scss.

Naming rocks!

For me, the proposed naming has increased my speed when developing. It also makes it easier to onboard new developers to a project and it drastically improves code quality if you have a naming scheme that does not feel arbitrary. 

Let's see how this will evolve in the future and let us know what you think of it!

Dein Besuch auf unserer Website produziert laut der Messung auf websitecarbon.com nur 0,28 g CO₂.