BEM (Block Element Modifier) is a highly useful, powerful, and simple naming convention that makes your front-end code easier to read and understand, easier to work with, easier to scale, more robust and explicit, and a lot more strict.

Block

Encapsulates a standalone entity that is meaningful on its own. While blocks can be nested and interact with each other, semantically they remain equal; there is no precedence or hierarchy.

  <div class="block">
    <p>Block</p>
</div>

  .block {
    width: 100%;
    color: white;
    display: block;
    background-color: black;
}

Element

Parts of a block and have no standalone meaning. Any element is semantically tied to its block. Any DOM node within a block can be an element. Within a given block, all elements are semantically equal.

  <div class="block">
    <div class="block__element">
        <p>Element inside block</p>
    </div>
</div>

  .block {
    width: 100%;
    color: white;
    display: block;
    background-color: black;    
}

.block__element {
    padding: 10px 15px;
}

Modifier

Flags on blocks or elements. Use them to change appearance, behavior or state.

  <div class="block block--white">
    <div class="block__element">
        <p>Block element with modified</p>
    </div>
</div>

  .block {
    width: 100%;
    color: white;
    display: block;
    background-color: black;
}

.block.block--white {
    color: black;
    background-color: white;
}

.block__element {
    padding: 10px 15px;
}

Using SCSS

The & (ampersand) is an advantageous feature in SCSS. Used them when nesting. It can be an excellent time-saver when you know how to use it, or a bit of a time-waster when you're struggling and could have written the same code in regular CSS.

  .block {

    width: 100%;
    color: white;
    display: block;
    background-color: black;

    &__element {
        padding: 10px 15px;
    }

    &.block--white {
        color: black;
        background-color: white;
    }

}

I have a long name and a few modifiers

Use & FTW...

  .blockname {

    width: 100%;
    color: white;
    display: block;
    background-color: black;

    &__element {
        padding: 10px 15px;
    }

    &#{&}--white {
        color: black;
        background-color: white;
    }

    &#{&}--red {
        color: white;
        background-color: red;
    }

    &#{&}--blue {
        color: white;
        background-color: blue;        
    }

}

  /** COMPILED CSS **/

.blockname {
    width: 100%;
    color: white;
    display: block;
    background-color: black;
}

.blockname__element {
    padding: 10px 15px;
}

.blockname.blockname--white {
    color: black;
    background-color: white;
}

.blockname.blockname--red {
    color: white;
    background-color: red;
}

.blockname.blockname--blue {
    color: white;
    background-color: blue;
}

...or use variable...

  $blockName: 'blocklongname';

.#{$blockName} {

    width: 100%;
    color: white;
    display: block;
    background-color: black;

    &__element {
        padding: 10px 15px;
    }

    &.#{$blockName}--white {
        color: black;
        background-color: white;
    }

    &.#{$blockName}--red {
        color: white;
        background-color: red;
    }

    &.#{$blockName}--blue {
        color: white;
        background-color: blue;
    }

}

  /** COMPILED CSS **/

.block {
    width: 100%;
    color: white;
    display: block;
    background-color: black;
}
.block__element {
    padding: 10px 15px;
}
.block.block--white {
    color: black;
    background-color: white;
}
.block.block--red {
    color: white;
    background-color: red;
}
.block.block--blue {
    color: white;
    background-color: blue;
}

..or set the parent as a variable:

  .blockname {

    $b: &; // Set the parent as a variable (b = block)

    width: 100%;
    color: white;
    display: block;
    background-color: black;

    &__element {
        padding: 10px 15px;
    }

    &#{$b}--white {

        color: black;
        background-color: white;

        #{$b}__element {
            color: orange;
        }

    }

    &#{$b}--red {
        color: white;
        background-color: red;
    }

    &#{$b}--blue {
        color: white;
        background-color: blue;        
    }

}

  /** COMPILED CSS **/

.blockname {
    width: 100%;
    color: white;
    display: block;
    background-color: black;
}

.blockname__element {
    padding: 10px 15px;
}

.blockname.blockname--white {
    color: black;
    background-color: white;
}

.blockname.blockname--white .blockname__element {
    color: orange;
}

.blockname.blockname--red {
    color: white;
    background-color: red;
}

.blockname.blockname--blue {
    color: white;
    background-color: blue;
}

Don't worry; variables stay within the scope they are declared. This won't work:

  .blockname {
  $b: &;
}

#{$b}__element {} // undefined variable $b

Conclusion

I hated BEM at the start, most of the people hated this method, but in the end, it made my life and writing code easier, now I can't imagine working any other way. It will help you maintain your SCSS. Maybe this isn't the perfect solution, but it sure helps me and everyone on my team!


995 2 36