Stylesheets
or the proper way to use BEM in your stylesheets

Guides are not rules and should not be followed blindly. Use your head and think.

A simple form block using BEM could look like this:

<form class="login-form">
  <div class="login-form__row">
    <label class="login-form__label">Username:</label>
    <input class="login-form__input login-form__input--username" />
  </div>
  <div class="login-form__row">
    <label class="login-form__label">Password:</label>
    <input class="login-form__input login-form__input--password" />
  </div>
</form>

Where the class login-form is the block name, classes login-form__row, login-form__label and login-form__input are elements and classes login-form__input--username and login-form__input--password are modifiers.

Blocks

Syntax: <block-name>

Block naming

Block name is a dash separated list of words describing the block and its use.

Care should be taken not to use too abstract or vague names. Names such as button or list should be avoided as they couldn't be properly defined to fit everywhere. As such you cannot reuse them properly. Too specific names are also not very useful, as they could prevent reuse on other parts of the page.

<div class="my-block">
  <!--...-->
</div>
.my-block {
  /* ... */
}

Good names:

.blog-article,
.breadcrumbs,
.pagination,
.avatar-image,
.language-picker

Bad names:

.list,
.main,
.content,
.footer-language-button,
.header-main-navigation-language-button

Block modifiers

Syntax: <block-name>--<block-modifier-name>

A block modifier is a class used to modify the appearance of a block in a certain context. A block modifier name is a dash spearated list of names prefixed with the block name and two dashes.

.my-block {
  /* ... */

  &.my-block--my-modifier {
    /* ... */
  }
}
<div class="my-block my-block--my-modifier">
  <!--...-->
</div>

Block usage

Not everything is a block. This is not Minecraft. Just because an HTML element has children doesn't necessarily mean it is, or should be a block. If an HTML element, and its styling makes no sense in the layout anywhere outside its position, it is not a block. If an HTML element cannot be reused, it is probably not a block. If an HTML element has no children, it is probably not a block. There are cases where this is not true, as each case is unique.

A bad block example

<div class="main-navigation">
  <ul class="main-navigation__list link-list">
    <li class="link-list__item item">
      <a href="#" class="item__link">
    </li>
    <li class="link-list__item item">
      <a href="#" class="item__link">
    </li>
  </ul>
</div>
.main-navigation {
  /* ... */

  .main-navigation__list {
    /* ... */
  }
}

.link-list {
  /* ... */

  .link-list__item {
    /* ... */
  }
}

.item {
  /* ... */

  .item__link {
    /* ... */
  }
}

The "item" block is not really a block, it is actually only meaningful under the link-list (or even main-navigation) block. As such it should just be an element, even though it has a child element.

Fixed example

<div class="main-navigation">
  <ul class="main-navigation__list link-list">
    <li class="link-list__item">
      <a href="#" class="link-list__link">
    </li>
    <li class="link-list__item">
      <a href="#" class="link-list__link">
    </li>
  </ul>
</div>
.main-navigation {
  /* ... */

  .main-navigation__list {
    /* ... */
  }
}

.link-list {
  /* ... */

  .link-list__item {
    /* ... */
  }

  .link-list__link {
    /* ... */
  }
}

Elements

Syntax: <block-name>__<element-name>

Element naming

Element name is a dash separated list of words describing the element and its use and purpose under its block. It is prefixed with the block name and two underscores or just two underscores as a shorthand. Usage of full name is recommended as overriding behavior might occur otherwise.

Unlike blocks, element naming can be abstract and vague, as it is only meaningful under its parent block. Still, care should be taken to have names that describe the element's use in a block. There is no point in using the block name in the element name, as that would only bring redundancy. A nice thing from SASS to use for writing elements is the parent - & symbol. A block with an element can be written in sass as:

.my-block {
  /* ... */

  &__my-element {
    /* ... */
  }
}

Resulting in css:

.my-block {
  /* ... */

}

.my-block__my-element {
  /* ... */
}

If you actually need it to nest inside of the block class, in the SASS you would have to use the & before the element, or use string interpolation.

Example:

.my-block {
  /* ... */

  & &__my-element {
    /* ... */
  }
  /* OR */
  #{&}__my-element {
    /* ... */
  }
}

Results in:

.my-block {
  /* ... */

}
  .my-block .my-block__my-element {
   /* ... */
  }

Where the & will interpolate into the block name. Use it.

Examples:

<div class="my-block">
  <div class="my-block__my-element">
    <!--...-->
  </div>
</div>
.my-block {
  /* ... */

  .my-block__my-element {
    /* ... */
  }
}

Good names:

.<block-name>__item,
.<block-name>__link,
.<block-name>__title,
.<block-name>__row,
.<block-name>__column

Bad names:

.<block-name>__blog-article-title,
.<block-name>__header-list,
.<block-name>__element /* Too vague even for an element */

Element modifiers

Syntax:

<block-name>__<element-name>--<element-modifier-name>

An element modifier is a class used to modify the appearance of a element in a certain context. A element modifier name is a dash separated list of names prefixed with the element name and two dashes.


.my-block {
  /* ... */

  &__my-element {
    /* ... */

    &--my-modifier {
      /* ... */
    }
  }
}
<div class="my-block">
  <div class="my-block__my-element my-block__my-element--my-modifier">
    <!--...-->
  </div>
</div>

Element usage

Elements only make sense inside a block. Never should an element be without its block, either in HTML or SASS. When reusing the block, its elements don't necessarily have to be used in the same order, or at all.

Bad elements example

<div class="statistics-list">
  <div class="statistics-list__statistic statistic">
    <span class="statistic__plain-text">Over</span>
    <h1 class="highlighted">
      <span class="highlighted__text">22</span>
    </h1>
    <span class="statistic__plain-text">years of experience.</span>
  </div>
  <div class="statistics-list__statistic statistics-list__statistic--no-first statistic">
    <h1 class="highlighted">
      <span class="highlighted__text">6</span>
    </h1>
    <span class="statistic__plain-text">Countries</span>
  </div>
</div>
.statistics-list {
  /* ... */

  &__statistic {
    /* ... */

    &--no-first {
      /* ... */
    }
  }
}

.statistic {
  /* ... */

  &__plain-text {
    /* ... */
  }
}

.highlighted {
  /* ... */

  &__text {
    /* ... */
  }
}

The highlighted block is not really a block, it is an element, as it can only live inside of the statistic block. Also, the highlighted__text element it houses also makes sense only inside the statistic, so it is an element of statistic, and not highlighted.

The statistics-list__statistic--no-first modifier doesn't make sense, as the modifier should be applied to the statistic block. The statistics-list__statistic element shouldn't worry about its content implementation, it should only have styles based on its position and appearance inside the "statistics-list" block.

Fixed example

<div class="statistics-list">
  <div class="statistics-list__statistic statistic">
    <span class="statistic__plain-text">Over</span>
    <h1 class="statistic__highlighted">
      <span class="statistic__text">22</span>
    </h1>
    <span class="statistic__plain-text">years of experience.</span>
  </div>
  <div class="statistics-list__statistic statistic statistic--no-first">
    <h1 class="statistic__highlighted">
      <span class="statistic__text">6</span>
    </h1>
    <span class="statistic__plain-text">Countries</span>
  </div>
</div>
.statistics-list {
  /* ... */

  &__statistic {
    /* ... */

  }
}

.statistic {
  /* ... */

  &--no-first {
    /* ... */
  }

  &__plain-text {
    /* ... */
  }

  &__highlighted {
    /* ... */
  }

  &__text {
    /* ... */
  }
}

Other notes