BEM Mixins

Avatar of Kitty Giraudel
Kitty Giraudel on (Updated on )

The best introduction to BEM is from Harry Roberts:

BEM – meaning block, element, modifier – is a front-end naming methodology thought up by the guys at Yandex. It is a smart way of naming your CSS classes to give them more transparency and meaning to other developers. They are far more strict and informative, which makes the BEM naming convention ideal for teams of developers on larger projects that might last a while.

Since Sass 3.3, we can write things like this:

.block {
    /* CSS declarations for `.block` */

    &__element {
        /* CSS declarations for `.block__element` */
    }

    &--modifier {
        /* CSS declarations for `.block--modifier` */

        &__element {
            /* CSS declarations for `.block--modifier__element` */
        }
    }
}

As long as CSS rules are short and base selector is simple, readability remains okay. But when things get more complex, this syntax makes it hard to figure out what’s going on. Because of this, we might be tempted to build two wrapper mixins for our BEM syntax:

/// Block Element
/// @access public
/// @param {String} $element - Element's name
@mixin element($element) {
    &__#{$element} {
        @content;
    }
}

/// Block Modifier
/// @access public
/// @param {String} $modifier - Modifier's name
@mixin modifier($modifier) {
    &--#{$modifier} {
        @content;
    }
}

Rewriting our previous example with our brand new mixins:

.block {
    /* CSS declarations for `.block` */

    @include element('element') {
        /* CSS declarations for `.block__element` */
    }

    @include modifier('modifier') {
        /* CSS declarations for `.block--modifier` */

        @include element('element') {
            /* CSS declarations for `.block--modifier__element` */
        }
    }
}

Note that quotes around strings are optional, we only add them for extra readability.

Now, if you feel like element and modifier are too long to type, you can create two shorter aliases like so:

/// @alias element
@mixin e($element) {
    @include element($element)  {
        @content;
    }
}

/// @alias modifier
@mixin m($modifier) {
    @include modifier($modifier) {
        @content;
    }
}

Using aliases:

.block {
    /* CSS declarations for `.block` */

    @include e('element') {
        /* CSS declarations for `.block__element` */
    }

    @include m('modifier') {
        /* CSS declarations for `.block--modifier` */

        @include e('element') {
            /* CSS declarations for `.block--modifier__element` */
        }
    }
}