The text below already became obsolete. Read the newest article instead.
BEM is an approach to front-end development designed with flexibility and ease of modification in mind.
BEM helps solve the following problems:
Block is an independent entity, a "building block" of an application.
Blocks contain information about themselves and their children (block elements).
Blocks can be used on their own or as a part of other blocks.
Example
b-search - a search form block

Element is a part of a block, that performs a certain function.
Block elements can only appear inside their respective blocks. Elements can be mandatory and optional.
Example
An input field and a button are elements of the b-search block

Modifiers are properties of blocks and elements; they change appearance or behavior of the elements, they are applied to.
Each modifier has a name and a value. Multiple modifiers can be applied simultaneously.
Example
A b-search block modifier sets the background color of a block

A project can consist of several sets of block implementations. Each set, or level, extends the higher-level set. The final implementation of a block is assembled by building the levels sequentially.
Example

Block names are defined as prefix-block-name.
Examples
b-menu
b-popup
i-popup
We commonly use two prefixes to define the designation of a block.
b- (as in block)
The b- prefix is used for blocks that have a user interface or, more generally, a visual representation.
Example
A popup window has a visual representation. It may, or may not, contain a close button, or have a balloon-like appearance. It can be displayed in different directions or have different color schemes.

i- (as in include)
The i- prefix is used for abstract blocks, which do not exist on their own, but are used to build other blocks.
i- blocks do not have a visual representation, they only implement some logic.
Example
The i-popup block does not have a visual representation, but it implements certain logic required by the b-popup block, which cannot exist without i-popup.

Element names specify unambiguously, which block the element belongs to.
Element names are defined as: b-block-name__element-name
Examples
b-menu__item
b-popup__content
Modifier names specify unambiguously, which block the modifier belongs to. Fully qualified modifier names are defined as: b-block-name_modifier-name_modifier-value.
Examples
b-menu_layout_horiz
b-menu_layout_vert
b-popup_direction_up
Modifier names specify unambiguously, which block and which element the modifier belongs to. Fully qualified modifier names are defined as: b-block-name__element-name_modifier-name_modifier-value.
Examples
b-menu__item_state_current
b-popupa__content_visibile_yes
b-popupa__content_visibile_no
Blocks can be modified using:
A modifier class is added to a block or an element, and it contains the necessary appearance or behavior changes.
Examples
A b-popup block does not have background set by default.

By adding a theme modifier to the b-popup block, background color can be specified for this block.
theme=yellow specifies a yellow background:

theme=black specifies a black background:

A block can have several modifiers applied at once.
Examples
theme modifier specifies background color, direction modifier specifies dropdown behavior (whether popups should open to the left, right, etc).
theme=yellow and direction=left — popup window with yellow background, opens to the left:

theme=yellow and direction=right — popup window with yellow background, opens to the right:

Modifiers can alter the blocks' structure (by adding/removing elements) and implementation.
Example
A has-close=yes modifier adds a closing button and adjusts block's padding accordingly.

A block can appear or behave differently, when put inside another block.
Example
Text color of the embedded block changes from green to red, when put inside a block with blue background.
Examples
b-lang-switcher - language switcher block

b-lang-switcher block located in the footer (b-foot) - font size becomes smaller.

Appearance or behavior changes can be introduced on a higher level.
Example
The common part of the block's implementation belongs to the framework (and is stored in the framework's repository) while some local modifications belong to a specific project (and are stored in the project's repository in separate files).
See bem-bl-test for an example of modifying the common b-link implementation to suit the needs of the bem-bl-test project.
Blocks are implemented using multiple technologies:
Depending on the puprose of a block, different sets of technologies can be used.
File system layout follows the naming conventions we described earlier. Multiple variants are possible as described below.
blocks/
b-menu/
_layout/
b-menu_layout_horiz.css
b-menu_layout_horiz.bemhtml
b-menu_layout_vertical.css
b-menu_layout_vertical.bemhtml
__elem/
b-menu__elem.css
b-menu__elem.bemhtml
b-menu.css
b-menu.js
b-menu.bemhtml
blocks/
b-menu/
b-menu_layout_horiz.css
b-menu_layout_horiz.bemhtml
b-menu_layout_vertical.css
b-menu_layout_vertical.bemhtml
b-menu__elem.css
b-menu__elem.bemhtml
b-menu.css
b-menu.js
b-menu.bemhtml
blocks/
b-menu/
b-menu.css
b-menu.js
b-menu.bemhtml
blocks/
b-menu_layout_horiz.css
b-menu_layout_horiz.bemhtml
b-menu_layout_vertical.css
b-menu_layout_vertical.bemhtml
b-menu__elem.css
b-menu__elem.bemhtml
b-menu.css
b-menu.js
b-menu.bemhtml
blocks/
b-menu.css
b-menu.js
b-menu.bemhtml
BEM blocks are usually implemented using multiple technologies.

Two different approaches to HTML markup are possible:
http:clubs.ya.ru/bem/replies.xml?item_no=712
Each BEM entity is defined by an HTML tag and corresponding CSS classes.
<div class="block-name">
<i class="block-name__elem"></i>
...
</div>
<div class="block-name block-name_modifier">...</div>Making one step further, we can partially replace standard HTML tags with custom ones.
<copyright>
<copyright-elem>...</copyright-elem>
...
</copyright>
<copyright class="block-name_modifier">...</copyright>Each BEM entity must have a CSS class to allow modification.
As blocks are inherently non-unique and can be reused, only CSS classes are allowed, not IDs.
Important: ID-based CSS selectors are *NOT ALLOWED*:
#header {}The naming of CSS classes of BEM entities must follow the [naming conventions](#naming)
Examples of naming
.b-popup {} // CSS class of a block
.b-popup__content {} // CSS class of an element
.b-popupa_theme_yellow {} // CSS class of a modifierUsage of type selectors is allowed but actively discouraged.
Examples of non-recommended selectors:
p
{
color: #ccc;
}
table.news td
{
border-bottom: 1px solid #ccc;
}
.list li
{
float: left;
}Avoiding of type selectors significantly improves page rendering performance, known as Reflow Time — time spent by the browser during application of a stylesheet to a DOM tree.
More information is provided in this blog post (in Russian)
JavaScript code can also be written in BEM terms - for example, instead of working with CSS classes directly, we can add, remove, or test for blocks, elements, modifiers. The exact DOM representation is treated as a low-level implementation detail.
Blocks without a DOM representation are allowed as well - they usually provide helper functionality.
Examples of blocks without a DOM representation:
i-request // Generic request generator
i-request_type_ajax // Ajax request generatorA client-side JS framework called i-bem is provided as part of the bem-bl library:
Blocks can be implemented using templates, which use some input data to build HTML.
The bem-bl library uses bemhtml as a templating mechanism.
bemhtml is a superset of the xjst templater. Templates written in bemhtml are compiled down to plain JavaScript and can be executed both in server- and client-side environments.
In the simplest form, a block is represented by a single DOM node, but generally blocks and DOM nodes are not the same thing.
Mixins are just that - usage of several blocks and/or elements on the same DOM node.
A single DOM node can represent:
Example
The tabbed pane block includes tabs (b-tabbed-pane__tabs) and panels (b-tabbed-pane__panels) as its elements. Both elements are applied to a single DOM node. This allows toggling of the panel's visual representation from vertical to horizontal.
Vertical tabbed pane

<div class="b-tabbed-pane b-tabbed-pane__tabs">
...
</div>
<div class="b-tabbed-pane b-tabbed-pane__panels">
...
</div>Horizontal tabbed pane

<table class="b-layout-table">
<tr>
<td class="b-layout-table__column b-layout-table__column_side_left">
<div class="b-tabbed-pane b-tabbed-pane__tabs">
...
</div>
</td>
<td class="b-layout-table__column b-layout-table__column_side_right">
<div class="b-tabbed-pane b-tabbed-pane__panels">
...
</div>
</td>
</tr>
</table>A typical BEM project contains one or more block levels and the page code itself.
The following layout examples are recommendations, not requirements.
A page is the sum total of files that define visual appearance and behavior of a given page.
Example
pages/
index/
index.css
index.js
index.bemhtml
index.bemdecl.js
index.bemjson.js
Pages are defined using a block declaration file (.bemdecl) and a block implementation file (.bemjson). These two are the "page source" and are used to generate the final CSS and JS code.
The b-page page uses b-menu and b-link blocks.
Example
The b-page page uses b-menu and b-link blocks.
Example
({
block: 'b-page',
content: {
block: 'b-menu',
mods: { layout: 'horiz', theme: 'red' },
content: [
{
elem: 'item',
elemMods: { state: 'current' },
content: 'Home page'
},
{
elem: 'item',
content: {
block: 'b-link',
url: '/',
content: 'My bookmarks'
}
},
{
elem: 'item',
content: {
block: 'b-link',
url: '/',
content: 'Search'
}
},
{
elem: 'item',
content: {
block: 'b-link',
url: '/',
content: 'About'
}
}
]
}
})The b-page page uses b-menu and b-link blocks
Example
@import url(../../bem-bl/blocks-desktop/b-menu/b-menu.css);
@import url(../../bem-bl/blocks-desktop/b-menu/item/b-menu__item.css);
@import url(../../bem-bl/blocks-desktop/b-menu/item/_state/b-menu__item_state_current.css);
@import url(../../bem-bl/blocks-desktop/blocks/b-menu/_layout/b-menu_layout_horiz.css);
@import url(../../bem-bl/blocks-desktop/b-link/b-link.css);
@import url(blocks/b-menu/_theme/b-menu_theme_red.css);The b-page page uses b-menu and b-link blocks
include("../../bem-bl/blocks-desktop/i-jquery/__inherit/i-jquery__inherit.js");
include("../../bem-bl/blocks-desktop/i-jquery/__identify/i-jquery__identify.js");
include("../../bem-bl/blocks-desktop/i-jquery/__is-empty-object/i-jquery__is-empty-object.js");
include("../../bem-bl/blocks-desktopery/__debounce/i-jquery__debounce.js");
include("../../bem-bl/blocks-desktop/i-jquery/__observable/i-jquery__observable.js");
include("../../bem-bl/blocks-desktop/i-bem/i-bem.js");
include("../../bem-bl/blocks-desktop/i-bem/__internal/i-bem__internal.js");
include("../../bem-bl/blocks-desktop/i-jquery/__stringify/i-jquery__stringify.js");
include("../../bem-bl/blocks-desktop/i-bem/html/i-bem__html.js");
include("../../bem-bl/blocks-desktop/i-jquery/__leftclick/i-jquery__leftclick.js");
include("../../bem-bl/blocks-desktop/i-bem/__dom/i-bem__dom.js");
include("../../bem-bl/blocks-desktop/i-bem/__dom/_init/i-bem__dom_init_auto.js");A project can consist of several sets of block implementations. Each set, or level, extends the higher-level set. A minimum of 1 set is required.

A block can be defined on several levels. A combination of levels used can be defined on a per-page level. The final implementation of the block is assembled by building the levels sequentially.
project/
blocks/
b-head/
b-head.css
b-head.bemhtml
b-foot/
b-foot.css
b-foot.bemhtml
b-sidebar/
b-sidebar.css
b-sidebar.bemhtml
project/
blocks/
b-head/
b-head.css
b-head.bemhtml
b-foot/
b-foot.css
b-foot.bemhtml
b-page/
b-page.bemhtml
b-sidebar/
b-sidebar.css
b-sidebar.bemhtml
pages/
index/
blocks/
b-head/
b-head.css
# b-head is redefined for the index page
about/
blocks/
b-about-text/
# a new block added specifically for the index page
b-about-text.css
b-about-text.bemhtml
project/
framework/
b-menu/
b-menu.css
b-menu.bemhtml
b-page/
b-page.css
b-page.bemhtml
blocks/
b-head/
b-head.css
b-head.bemhtml
b-foot/
b-foot.css
b-foot.bemhtml
b-page/
# redefines the b-page block defined on a higher (framework) level
b-page.bemhtml
b-sidebar/
b-sidebar.css
b-sidebar.bemhtml
project/
framework/
b-menu/
b-menu.css
b-menu.bemhtml
b-page/
b-page.css
b-page.bemhtml
blocks/
b-head/
b-head.css
b-head.bemhtml
b-foot/
b-foot.css
b-foot.bemhtml
b-page/
# Redefines the b-page block defined on a higher (framework) level
b-page.bemhtml
b-sidebar/
b-sidebar.css
b-sidebar.bemhtml
pages/
index/
blocks/
b-head/
b-head.css
# b-head is redefined for the index page
about/
blocks/
b-about-text/
# a new block added specifically for the index page
b-about-text.css
b-about-text.bemhtml
project/
blocks/
b-head/
b-head.css
b-head.bemhtml
b-foot/
b-foot.css
b-foot.bemhtml
b-page/
# Redefines the b-page block defined on a higher (framework) level
b-page.bemhtml
b-sidebar/
b-sidebar.css
b-sidebar.bemhtml
pages/
index/
blocks/
b-head/
b-head.css
# b-head is redefined for the index page
about/
blocks/
b-about-text/
# a new block added specifically for the index page
b-about-text.css
b-about-text.bemhtml
themes/
black/
# Files, which define the 'black' color scheme (stored in the same directory)
b-head.css
b-foot.css
b-sidebar.css
yellow/
b-head.css
b-foot.css
b-sidebar.css
Blocks are implemented using multiple technologies:
Depending on the puprose of a block, different sets of technologies can be used.
Structure matters most - implementation details are secondary.
Example of a b-domik block (login form)
Домик на странице
|
Домик в попапе
|
b-domik/
# common files
b-domik.css
b-domik.ie.css
b-domik.js
b-domik.xsl
# modifiers
_type/
b-domik_type_onpage.css # login form on the page
b-domik_type_onpage.ie.css
b-domik_type_onpage.js
b-domik_type_onpage.xsl
b-domik_type_popup.css # login form in a popup
b-domik_type_popup.ie.css
b-domik_type_popup.js
b-domik_type_popup.xsl
__lock/
# "lock" element (denotes secure login)
b-domik__lock.css
b-domik__lock.png
b-domik__lock.xsl
_visibility/
# a modifier of the "lock" element which makes the element visible
b-domik__lock_visibility_visible.css
__shadow/
# "shadow" element
b-domik__shadow.css
b-domik__shadow.ie.css
b-domik__shadow.png
bem-tools command-line tools are being developed to enhance development experience. BEM tools include a command-line utility, that can be used to quickly create BEM source files using different technologies (HTML/CSS/JS), and a BEM compiler.
Main repository is at bem-tools