BEM

B__E--M

BEM stands for "Block Element Modifier".

BEM Rules

  • Only classes. No IDs or tags
  • Nested HTML and Flat CSS

BEM Advantages

  • Inherently adopts OOCSS best practices
  • Flexible and easy to extend/re-use/maintain/refactor
  • Declarative classes and self-documented code
  • Easy to change DOM structure without changing CSS
  • Flat CSS what is easy to override if needed

BEM Block

  • Name is noun
  • Works as a namespace
  • Can be nested inside each other

Examples: .header, .menu, .btn.

BEM structure
BEM structure

BEM Element

  • Name is noun
  • Separated from block name with 2 underscores
  • Always part of a block with same namespace
  • Can be nested inside each other

Examples: .menu__item, .search-form__input, .search-form__btn.

BEM element
BEM element

BEM Modifier

  • Name is adjective and defines the appearance, state, or behavior of a block or an element
  • Separated from block or element name with 2 dashes
  • Can not be used without block or element class

Examples: header--fixed, .menu__item--active, .search-form--dark, .search-form__input--small, .search-form__input--success, .search-form__btn--disabled.

BEM modifier
BEM modifier

Should I Create Block or Element?

  • Create an element if it cannot be used without or outside the block
  • Create new block if you plan to reuse it somewhere else

Example: .btn vs .menu__item.

Prefixes

  • .c-search-form - reusable components
  • .u-color-success - utility helper classes with single function. Often using
    !important to boost their specificity
  • .js-search-form-btn - JavaScript only classes. No styles attached
<div class=”c-search-form”>
<input class=”c-search-form__input u-color-success” type=”text”>
<input class=”c-search-form__btn js-search-form-btn” type=”button”>
</div>

Example:

CSS inheritance issue

CSS:

.article .title {
  color: red;
  border: 1px solid green;
}

.section .title {
  color: blue;
}

HTML:

<div class="article">
	<h3 class="title">Article Title</h3>

	<div class="section">
		<h3 class="title">Section Title</h3>
	</div>
</div>

The issue: "Section Title" also have border just like "Article Title" because of CSS Inheritance.

CSS inheritance issue - the BEM solution

.article { }
.article__title {
  color: red;
  border: 1px solid green;
}

.section { }
.section_title {
  color: blue;
}

Styling context issue

Client request: “Add border top to product list on search page”.

.page-search .product-list {
  border-top: 1px solid black;
}

Developer's dilemma: Where should code go? Into product-list.css or page-search.css? Probably into page-search.css because it is related to search page.

Client request #2: “Add border top to product list on popular category page like on the search page.”

.page-search .product-list, 
.page-category-popular .product-list {
  border-top: 1px solid black;
}

Developer dilemma #2: “Where should code go? How to re-use code properly?”
“Should we put it into product-list.css or duplicate the code into page-search.css and page-category-popular.css?”

Client request #3: “Where is the border on the category popular page?”

The developer debug the code and one hour later discovers that somebody changed name of category from “Popular” to “Featured” and class hierarchy does not work.

Styling context issue - the BEM solution

So where was the issue? The issue started with the questions is “Where is it?”. With "where is it?" you start to think where apply the fix. We should ask “What is it?” instead of “Where
is it?”. Do not use context specific approach when you need to use components approach.

Client request: “Add border top to product list on search page”.

Developer: “I need to add a border. I need to have the same product list just with the border. So what is it? It is the same product list with border variation."

So with this approach it is easy to re-use and extend the code. And also it is self-documented and error-prone.

CSS:

.product-list {}
.product-list--border-top {
  border-top: 1px solid black;
}

HTML:

<div class=”product-list
product-list--border-top”></div>

Sources: