Quick notes on BEM (Block Element Modifier) syntax in CSS
What is it?
- What itโs not:
- A CSS framework (like Bulma, Bootstrap)
- Library
- Itโs a naming convention for classes in HTML and CSS
- Alternatives of naming conventions include
- Object Oriented CSS (OOCSS)
- Scalable and Modular Architecture for CSS (SMACSS)
- Atomic CSS
How to use it
- Block: higher level component
- Element: descendent of block, relies on block
- Modifier: represents different state or version of block/element
.block {
}
.block__element {
}
.block--modifier {
}
For example, in JSX:
<div
className={`block ${isSelected ? "block--selected" : ""} ${
warning ? "block--warning" : ""
}`}
>
<div className="block__element"></div>
</div>
A โreal worldโ example:
.person {
}
.person__hand {
}
.person--male {
}
.person--male__hand {
}
.person__hand--left {
}
A real world example
Before BEM
.site-search {
}
.site-search.full {
}
.site-search .field {
}
<form class="site-search full">
<input type="text" class="field" />
<input type="Submit" value="Search" class="button" />
</form>
- Problem with above is that the
full
class and thefield
class might clash with class styles defined elsewhere
With BEM
.site-search {
} /* Block */
.site-search__field {
} /* Element */
.site-search--full {
} /* Modifier */
or
.site-search {
/* Block */
&__field {
} /* Element */
&--full {
} /* Modifier */
}
<!-- Notice that a modified element gets both the base block class and the modifier class -->
<form class="site-search site-search--full">
<input type="text" class="site-search__field" />
<input type="Submit" value="Search" class="site-search__button" />
</form>
Pros and cons
- ๐ Avoids name clashing against global scope
- ๐ Clear what to name a new class
- ๐ Clear understanding of how CSS matches up with HTML - clear what modifier should go with what block
- ๐ Follows components
- ๐ Maintains flexibility in a CSS world - so we are still open to mix in personal preferences - but this is still open to lack of consistency across a team
When mixed with global styles like the below, itโs flexible, but a new developer would need to know these helpers existed to use them.
.noBreakText {
white-space: nowrap;
}
.upperCase {
text-transform: uppercase;
}
- ๐ Other tools out there which solve the global scope problem (CSS modules, SvelteJS, Styled Components (React specific))
- ๐ Lack of clarity on what should be an โatomicโ modifier
- ๐ Is open to unnecessary nesting - when is something a new block? When does something need a new modifier?
e.g.
<div class="header">
<div class="logo"></div>
</div>
or
<div class="header">
<div class="header__logo"></div>
</div>