Block, Element, Modifier or BEM is an approach to front-end web development that helps you to create reusable UI elements.
Benefits
BEM has three main benefits that makes it attractive to use.
- It is easy to use. We simply need to adopt a naming convention.
- It promotes modularity. The independent blocks and CSS selectors that it encourages you to write makes your code reusable and loosely coupled.
- It gives your CSS a solid structure that remains straightforward to manage throughout the lifetime of your project.
An extra benefit that I really like is that it's wonderful to use with Elm.
What's a block?
A block is a standalone entity that is meaningful on its own.
For e.g. a button, slider, menu, modal or window.
What's an element?
An element is a part of a block that has no standalone meaning and is tied to its block.
For e.g. a menu item or a window's header.
What's a modifier?
A modifier is a flag or key-value attribute on a block or element that is used to change appearance or behavior.
Block
Naming
<block> ::= <name>
<name> ::= <letter> <alphanumeric>* ('-' <alphanumeric>+)?
<alphanumeric> ::= <letter> | <digit>
<letter> ::= 'a' | ... | 'z' | 'A' | ... 'Z'
<digit> ::= '0' | ... | '9'
A <name>
starts with a letter and is followed by zero or more alphanumeric characters. It's optionally followed by a hyphen and one or more alphanumeric characters.
A <block>
is any <name>
.
For e.g. button
, r2
, r2-d2
, c-3po
.
HTML
Any DOM node can be a block if it accepts a class name.
For e.g.
<button class="button">...</button>
CSS
- Use a class name selector only.
- Good:
.button {...}
- Good:
- No tag name or ids.
- Bad:
button.button {...}
,#id.button{...}
- Bad:
- No dependency on other blocks or elements on the page.
- Bad:
.window .button {...}
,.menu__item .button {...}
- Bad:
Element
Naming
<element> ::= <block> '__' <element-name>
<element-name> ::= <name>
An <element>
is a <block>
followed by double underscore followed by an
<element-name>
.
An <element-name>
is any <name>
.
For e.g. menu__item
, c-3po__head
HTML
Any DOM node (that accepts a class name) within a block can be an element.
For e.g.
<ul class="menu">
...
<li class="menu__item">...</li>
...
</ul>
CSS
- Use a class name selector only.
- Good:
.menu__item {...}
- Good:
- No tag name or ids.
- Bad:
li.menu__item {...}
,#id.menu__item{...}
- Bad:
- No dependency on other blocks or elements on the page.
- Bad:
.menu .menu__item {...}
,.window__header .menu__item {...}
- Bad:
Modifier
Naming
<modifier> ::= <block-modifier>
| <element-modifier>
<block-modifier ::= <block> '--' <modifier-name>
<element-modifier ::= <element> '--' <modifier-name>
<modifier-name> ::= <modifier-flag>
| <modifier-key> '--' <modifier-value>
<modifier-flag> ::= <name>
<modifier-key> ::= <name>
<modifier-value> ::= <name>
A block or an element can be modified. A <modifier-name>
can be used to
represent a boolean or key-value attribute.
For e.g.
- Boolean modifiers:
button--disabled
,menu__item--active
- Key-value modifiers:
button--size--large
,window__header--theme--xmas
HTML
A modifier is an extra class name which you add to a block or element DOM node. Add modifier classes only to the block or element they modify and keep the original class.
A good example:
<ul class="menu">
...
<li class="menu__item menu__item--active">...</li>
...
</ul>
A bad example:
<ul class="menu">
...
<!-- The original element class `menu__item` isn't kept. -->
<li class="menu__item--active">...</li>
...
</ul>
CSS
- Use modifier class name as selector.
- Good:
.button--disabled {...}
- Good:
- You're allowed to alter elements based on a block-level modifier.
- Good:
.menu--open .menu__item {...}
- Good:
Top comments (0)