This is my personal preference for writing BEM SCSS, I don't have any assumptions that this is 'the best way' or anything like that - just what works for me. I'm interested to hear any comments or suggestions, there's always room for improvement!
BEM allows us to use a single classname for an element (thus speeding up it's selection), while making it clear what elements belong to which blocks. This aids in maintainability, as you get context from a file without needing to see the DOM while not making our CSS dependent on the DOM structure.
BEM's methodology relies on the following naming convention: .block__element--modifier
, which you can read more about here.
The goals for this BEM style are:
- Single classname selectors
- Clear block-element context
- Clear element descriptors
- Effortlessly unique selectors
- Reusability of styles through SASS's @extend
This will be our top-level classname, such as .search-form
.
.block {
In our search form, we have certain elements that we want to style - so, maybe an input
. The resulting selector, through the use of SASS's &
feature would look like: .block__element
, or .search-form__input
in our example.
&__element {
width: 80%;
background-color: #bada55;
color: #fff;
}
Sometimes, we'll want to have a slightly different version of an element - say, --small
. We could nest our modifier in the element block, but that'd cause use of of @extend
on the element to include any modifiers, and we'd have to give our element two classnames or duplicate styles/selectors. So, instead, we copy the element selector and add our modifier to the end. We then use the @extend
directive, and add our differences. This shouldn't result in duplicated output styles, as the SASS compiler is smart enough to add to the __element
selector.
&__element--modifier {
@extend .block__element;
/* or, from our example: */
@extend .search-form__input;
width: 30%;
}
}
Communicating context inside our styles is beneficial, since that way we know what styles are related to others, or work in conjunction to build a part of the block. A nice way of doing this is to think of our blocks as having sub-blocks, such as __product
. We then use add our related elements into this sub-block, like so:
&__product {
&-image {
width: 75px;
height: 75px;
}
&-title {
font-size: 1.2em;
}
}
This now shows us that a product sub-block of this particular block contains a title and a image, and groups it all together nicely (it helps to enforce this, too!) so that if we don't even have to think about putting related elements together. This aids in maintainability, as finding everything related to a product in our block is simple, and reduces the need for the author to actively organise their SCSS.