Block Element Modifier Methodology

Block

A logically and functionally independent page component, the equivalent of a component in Web Components. A block encapsulates behavior (JavaScript), templates, styles (CSS), and other implementation technologies. Blocks being independent allows for their re-use, as well as facilitating the project development and support process.

<! -- Correct. The `error` block is semantically meaningful -->
<div class="error"></div>
<! -- Incorrect. It describes the appearance -->
<div class="red-text"></div>
  1. The block should not influence its environment, meaning you should not set the external geometry (margin) or positioning for the block.
  2. You also should not use CSS tag or IDselectors when using BEM.
  3. The blocks can re-use and can move from one place to another or form one project to another.

This ensures the necessary independence for reusing blocks or moving them from place to place.

Nesting Blocks

  1. Blocks can be nested in each other.
  2. You can have any number of nesting levels.
<! -- `header` block -->
<header class="header">
    <! -- Nested `logo` block -->
    <div class="logo"></div>

    <! -- Nested `search-form` block -->
    <form class="search-form"></form>
</header>

Element

A composite part of a block that cannot be used outside of it. The element name is separated from the block name with a double underscore (__).

<!-- `search-form` block -->
<form class="search-form">
    <!-- `input` element in the `search-form` block -->
    <input class="search-form__input">

    <!-- `button` element in the `search-form` block -->
    <button class="search-form__button">Search</button>
</form>

Ex: block-name__element-name

Nesting elements

  1. Elements can be nested inside each other.
  2. You can have any number of nesting levels.
  3. An element is always part of a block, not another element. This means that element names cannot define a hierarchy such as block__elem1__elem2.
<div class="block">
    <div class="block__elem1">
        <div class="block__elem2">
            <div class="block__elem3"></div>
        </div>
    </div>
</div>
.block {}
.block__elem1 {}
.block__elem2 {}
.block__elem3 {}

This allows you to change a block’s DOM structure without making changes in the code for each separate element:

<div class="block">
    <div class="block__elem1">
        <div class="block__elem2"></div>
    </div>

    <div class="block__elem3"></div>
</div>

Notes:

  1. An element is always part of a block, and you should not use it separately from the block.
  2. An element is an optional block component. Not all blocks have elements.
  3. Using elements within elements is not recommended.

Modifiers

An entity that defines the appearance, state, or behavior of a block or element. The modifier name is separated from the block or element name by a single underscore (_). The use of modifier is optional. Modifiers are similar in essence to HTML attributes. The same block looks different due to the use of a modifier. Modifiers can be changed in runtime (for example, as a reaction to a DOM event of the block), or via other blocks.

Ex: directions_left-top

Types of modifiers

  1. Boolean

Used when only the presence or absence of the modifier is important, and its value is irrelevant. For example, disabled. If a Boolean modifier is present, its value is assumed to be true.

The structure of the modifier’s full name follows the pattern:

block-name_modifier-name
block-name__element-name_modifier-name

<!-- The `search-form` block has the `focused` Boolean modifier -->
<form class="search-form search-form_focused">
    <input class="search-form__input">

    <!-- The `button` element has the `disabled` Boolean modifier -->
    <button class="search-form__button search-form__button_disabled">Search</button>
</form>

 2. Key – value

Used when the modifier value is important. For example, “a menu with the islands design theme”: menu_theme_islands.

The structure of the modifier’s full name follows the pattern:

block-name_modifier-name_modifier-value
block-name__element-name_modifier-name_modifier-value


<!-- The `search-form` block has the `theme` modifier with the value `islands` -->
<form class="search-form search-form_theme_islands">
    <input class="search-form__input">

    <!-- The `button` element has the `size` modifier with the value `m` -->
    <button class="search-form__button search-form__button_size_m">Search</button>
</form>

<!-- You cant use two identical modifiers with different values simultaneously -->
<form class="search-form
             search-form_theme_islands
             search-form_theme_lite">

    <input class="search-form__input">

    <button class="search-form__button
                   search-form__button_size_s
                   search-form__button_size_m">
        Search
    </button>
</form>

Guidelines to modifiers

  1. A modifier cannot be used alone.
<!--
    Correct. The `search-form` block has the `theme` modifier with
    the value `islands`
-->
<form class="search-form search-form_theme_islands">
    <input class="search-form__input">

    <button class="search-form__button">Search</button>
</form>

<!-- Incorrect. The modified class `search-form` is missing -->
<form class="search-form_theme_islands">
    <input class="search-form__input">

    <button class="search-form__button">Search</button>
</form>

2. Mix

A technique for using different BEM entities on a single DOM node.

Mixes allow you to:

  • Combine the behavior and styles of multiple entities without duplicating code.
  • Create semantically new UI components based on existing ones.
<!-- `header` block -->
<div class="header">
    <!--
        The `search-form` block is mixed with the `search-form` element
        from the `header` block
    -->
    <div class="search-form header__search-form"></div>
</div>

BEM Tree

A representation of a web page structure in terms of blocks, elements, and modifiers. It is an abstraction over a DOM tree that describes the names of BEM entities, their states, order, nesting, and auxiliary data.

In real-life projects, a BEM tree can be presented in any format that supports the tree structure.

Let us consider an example of a DOM tree:

<header class="header">
    <img class="logo">
    <form class="search-form">
        <input class="input">
        <button class="button"></button>
    </form>
    <ul class="lang-switcher">
        <li class="lang-switcher__item">
            <a class="lang-switcher__link" href="url">en</a>
        </li>
        <li class="lang-switcher__item">
            <a class="lang-switcher__link" href="url">ru</a>
        </li>
    </ul>
</header>

Implementation

  • behavior
  • appearance
  • tests
  • templates
  • documentation
  • description of dependencies
  • Additional data (e.g., images).

Naming Convention

  1. Names are written in lowercase Latin letters.
  2. Words are separated by a hyphen (-).
  3. The block name defines the namespace for its elements and modifiers.
  4. The element name is separated from the block name by a double underscore (__).
  5. The modifier name is separated from the block or element name by a single underscore (_).
  6. The modifier value is separated from the modifier name by a single underscore (_).
  7. For Boolean modifiers, the value is not included in the name.
  8. Boolean modifiers are separated from the name of the block or element by a double hyphen (–).
  9. The value of a modifier is separated from its name by a double hyphen (–).

Important: Elements of elements do not exist in the BEM methodology. The naming rules do not allow creating elements of elements, but you can nest elements inside each other in the DOM tree.

You can create your own custom naming solution for BEM entities. The most important thing is that your new naming system makes it possible to pro grammatically separate blocks from elements and modifiers.