DEV Community


BEM CSS Architecture and Sass

I've been tinkering with computers since I was a teen. I'm currently pivoting from my current role as Tech Support manager to Full Stack Web Developer. I'm actively seeking employment in the field.
・2 min read


BEM is a way of architecting your html in such a way that you can use a conventional set of classes in your CSS to style your pages using a system/convention. The way I think about it is that you group sections of the page together in a way that makes sense, and apply flags or toggles to the html in order to apply styles to it.

BEM stands for Block Element Modifier:

  • Block: a standalone entity, meaningful on its own (e.g. header, container, menu, checkbox, input, button).
  • Element: a part of a block that has no standalone meaning and is semantically tied to its block (e.g. menu-item, list-item, header-title).
  • Modifier: a flag on a block or element, used to change appearance and/or behavior (e.g. disabled, highlighted, checked, size-big, color-yellow).

There is a convention for BEM elements: double underscores after the block name indicates you're defining an element inside a block, and double dashes mean that you're defining a modifier. In the label element below is an example of an element inside a block (textfield__label).

<div class "textfield">
  <label for="first-name" class="textfield__label">
    First Name
  <input name="first-name" type="text" class="textfield__input" />

The use of this convention prevents collision with other elements because it is unlikely that another element will have the same class. Sass makes building these easier because of the ability to use the parent selector.

.textfield {
  &__input {}
  &__label {}
  &__validation-error {}

Continuing with the html example from above, the html would then look something like this:

<div class "textfield textfield--state--validated">
  <label for="first-name" class="textfield__label">
    First Name
  <input name="first-name" type="text" class="textfield__input" />
  <span class="texfield__validation-error">
    Must be two characters or longer

Note that because the parent selector can only be used once, there is a specific way to write the rules for the block element itself, which is why the textfield appears after the parent selector in the modifiers below:

.textfield {
  &.textfield--state-error {}
  &.textfield--state-validated {}

Discussion (0)