DEV Community

Dwayne Crooks
Dwayne Crooks

Posted on

My notes on BEM

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.

  1. It is easy to use. We simply need to adopt a naming convention.
  2. It promotes modularity. The independent blocks and CSS selectors that it encourages you to write makes your code reusable and loosely coupled.
  3. 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'
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

CSS

  • Use a class name selector only.
    • Good: .button {...}
  • No tag name or ids.
    • Bad: button.button {...}, #id.button{...}
  • No dependency on other blocks or elements on the page.
    • Bad: .window .button {...}, .menu__item .button {...}

Element

Naming

<element>      ::= <block> '__' <element-name>
<element-name> ::= <name>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

CSS

  • Use a class name selector only.
    • Good: .menu__item {...}
  • No tag name or ids.
    • Bad: li.menu__item {...}, #id.menu__item{...}
  • No dependency on other blocks or elements on the page.
    • Bad: .menu .menu__item {...}, .window__header .menu__item {...}

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

A bad example:

<ul class="menu">
  ...
  <!-- The original element class `menu__item` isn't kept. -->
  <li class="menu__item--active">...</li>
  ...
</ul>
Enter fullscreen mode Exit fullscreen mode

CSS

  • Use modifier class name as selector.
    • Good: .button--disabled {...}
  • You're allowed to alter elements based on a block-level modifier.
    • Good: .menu--open .menu__item {...}

Resources

Top comments (0)