Why does BEM often use two underscores instead of one for modifiers?
Double Underscore is used to define sub element of a block.
i.e:
<nav class="main-nav">
<a class="main-nav__item" href="#">Text</a>
</nav>
Where main-nav
is a block & main-nav__item
is a sub element.
This is done because some people might name their block like this main_nav
which will create confusion with single underscore like this : main_nav_item
Therefore double underscore will clarify stuff like this: main_nav__item
.
I'm going to 2nd @Imran Bughio's answer, but I'm trying to further clarify the issue.
In standard BEM style, single underscores are reserved for modifiers. Also, they usually represent a combination of key/value pairs. E.g.
.block_align_vertical
.block_align_horizontal
.block__element_size_big
.block__element_size_small
This is in contrast to the modified BEM syntax championed by inuit.css for example, which are boolean.
.block--vertical
.block--horizontal
.block__element--big
.block__element--small
From my experience when using the modified syntax, you quickly run into expression limitations. E.g. if you would write
.block--align-vertical
.block--align-horizontal
.block__element--size-big
.block__element--size-small
The key/value relation would not be unique, if you would try to describe a key such as background-attachment
which would result in
.block__element--background-attachment-fixed
Another added benefit is, that you can use the libraries based on the standard naming convention for added productivity in your workflow:
- http://bem.info/tools/bem/bem-tools/
- https://github.com/hoho/jquery-bem
It's also worth mentioning that the BEM syntax is not forced upon us and if you find another syntax that you find more readable then by all means go with that. The important thing is consistency, ensuring other developers work to the same syntax.
An example of an alternative syntax used is in SUIT CSS by Nicolas Gallagher. Which uses the following syntax.
ComponentName
ComponentName--modifierName
ComponentName-elementName
ComponentName.is-stateOfComponent
You can read more here SUIT CSS naming conventions
Because whose blocks can be hyphen or underscore delimited, for example:
.site-search {} /* Block */
.site-search__field {} /* Element */
.site-search--full {} /* Modifier */
or
.site_search {} /* Block */
.site_search__field {} /* Element */
.site_search--full {} /* Modifier */