Know your element (__
) from your modifier (--
). Both blocks and elements can have modifiers. (.b--m
, .b__e--m
).
In react lingo, BEM's "B" (for "Block") is a component.
Elements can nest deep in html, but the selector doesn't represent this deep nesting. (no .a__b__c
, instead just .a__c
- which can be in .a__b
).
The idea
The idea with BEM is to keep a flat hierarchy (don't nest selectors) with simple selectors - only one class per selector, and no IDs or element tags. By not nesting we have a low and consistent specificity of all html elements, which makes it possible to have modifications of styles without using !important
.
Don't ever use the html element as well as a class in the selector for this same reason (no button.button
), as well as not to lock oneself into having to use a specific type of element.
Only time nesting of selectors is allowed is if elements need changing when the block has a modifier class applied to it (.editor--dark .editor__text {color: white}
for example).
Use of html element selectors can be used at times, for example in the case of the flag above, where we need to wrap the img
in an element for styling, but might still want to apply styles to the img
without having another class (.flag__actual-image
is a bit ugly). But try to keep it to a minimum, and don't have "magic" elements, where (for example) a span in a .media
gets grey text and centered (give it a name instead, .media__caption
maybe?).
Since we scope every element and modifier, we are free to use whatever names we want - no risk of clashes between the icon called danger
and the button style called danger
.
**Example: **
Notice the two buttons which are both elements of the editor, as well as blocks in their own right, in two different ways.
Also, note that there are two navs, but one would be stuck to the top (--top
) and the other bottom, but they are both nav bars of the editor, and so share most styles (different variants/modifications of the same element).
Lastly, notice the use of icon--remove
even though we don't have icon
. Since we don't nest our selectors it's possible to "borrow" modifiers (and elements) from blocks without applying the full block styles. In this case icon--remove
sets the content of the :before
pseudo element to the right icon, but doesn't apply any base icon styles, something .icon
does but a button doesn't need. If we combined classes when making selectors .icon.icon--remove
this wouldn't be possible, only thanks to the flat hierarchy with simple selectors is this possible.
<div class="editor editor--dark-mode">
<div class="editor__nav editor__nav--top">
<input class="editor__filename" type="text" />
<button class="editor__button btn btn--danger btn--icon icon--remove">Move to trash</button>
</div>
<div class="editor__body">
...
</div>
<div class="editor__nav editor__nav--bottom">
<button class="editor__button btn btn--primary btn--icon icon--save">Save</button>
</div>
</div>