BEM (Block__Element--Modifier)

What is BEM

BEM or.. Block, Element, Modifier is a css methodology for naming CSS classes. Its main purposes is to reduce the specificity of a css rule, and to introduce a better naming convention which will organize your css, and improve development and maintenance.

What is a Block, an Element, and a Modifier?

Before i get into what each are, a quick note about style convention. Your class names should always be in lowercase, and hyphen-spaced. If there is some logical grouping that can be made for the name of the block, it should be named with the grouping first separated by a hyphen, ie picker-city and picker-date etc

Block

Head block components

Block is the top level of your component, for example a model box would look something like :

<aside class="model">
  <header>Model Title</header>
  <section>Model Content</section>
  <footer>Model Footer</footer>
</aside>
.model { ... }

Element

This a child element contained inside your block that is owned by the component, it is denoted by two underscores following the name of the block, ie model__title:

<aside class="model">
  <header class="model__title">Model Title</header>
  <section class="model__content">Model Content</section>
  <footer class="model__footer">Model Footer</footer>
</aside>
.model {
	...
	&__title { ... }
	&__content { ... }
	&__footer { ... }
}

Modifier

Modifiers change or rather build upon the element to modify them in someway. This allows you to make the base css for a block/element, and then have modifiers that will make deviations from the original. Modifiers are written with two hyphens ie model--error or modelfooter--disabled, but note that the original class must also be written i.e modelfooter model__footer--disabled:

<aside class="model model--error">
  <header class="model__title">Model Title</header>
  <section class="model__content">Model Content</section>
  <footer class="model__footer model__footer--disabled">Model Footer</footer>
</aside>
.model {
	...
	background: yellow;
	&--error { background: red; }
	&__title { ... }
	&__content { ... }
	&__footer {
		...
		display: block;
		&--disabled {
			display: none;
		}
	}
}

What about Blocks in Blocks?

It is perfectly fine to have blocks contained in another block independently named, ie:

<header class="header">
    <div class="logo header__logo"> ...</div>
    <div class="search header__search">
      <input class="search__input">
      <button class="search__btn">
    </div>
    <div class="user header__user"> ...</div>
</header>

What about modifiers outside of the scope of the block?

Sometimes a state may have changed outside the scope of the block that may need to be reflected in the styling, whilst BEM doesn't accommodate for this it can be addressed by going one level deeper in specificity.

This commonly occurs with JS making state changes on the page, for example... on a higher up block it may have is-fullscreen, in sass we can keep in the same scope but by using @at-root .is-fullscreen & { ... } and it will append a class to the rule:

<div id="app" class="is-fullscreen">
  ...
  <div class="map">
    <div class="map__tiles">
      <div class="map__ui"></div>
    </div>
  </div>
</div>
.map {
	&__tiles { ... }
	&__ui { ... }
	@at-root .is-fullscreen & { ... }
}
//will produce:
.map {
  ...;
}
.map__tiles {
  ...;
}
.map__ui {
  ...;
}
.is-fullscreen .map {
  ...;
}