HTML & CSS
Article
By Tiffany Brown

CSS Architecture Block-Element-Modifier (BEM)

By Tiffany Brown

The following is an extract from our book, CSS Master, written by Tiffany Brown. Copies are sold in stores worldwide, or you can buy it in ebook form here.

BEM, or Block-Element-Modifier, is a methodology, a naming system, and a suite of related tools. Created at Yandex, BEM was designed for rapid development by sizable development teams. In this section, we’ll focus on the concept and the naming system.

BEM methodology encourages designers and developers to think of a website as a collection of reusable component blocks that can be mixed and matched to create interfaces. A block is simply a section of a document, such as a header, footer, or sidebar, illustrated in Figure 2.3. Perhaps confusingly, “block” here refers to the segments of HTML that make up a page or application.

Figure 2.3. A home page might have header, main, and footer blocks

Blocks can contain other blocks. For example, a header block might also contain logo, navigation, and search form blocks as seen in Figure 2.4. A footer block might contain a site map block.

Figure 2.4. A header block that contains logo, navigation, and search blocks

More granular than a block is an element. As the BEM documentation explains:

An element is a part of a block that performs a certain function. Elements are context-dependent: they only make sense in the context of the block they belong to.

A search form block, for example, contains a text input element and a submit button element, as evident in Figure 2.5. To clarify, we’re using “element” in the design element sense rather than the HTML element sense.

Figure 2.5. A search block with text input and submit button elements

A main content block, on the other hand, might have an article list block. This article list block might contain a series of article promo blocks. And each article promo block might contain image, excerpt, and Read More elements, as presented in Figure 2.6.

Figure 2.6. A promotional block for a website article

Together, blocks and elements form the basis of the BEM naming convention. According to the rules of BEM:

  • Block names must be unique within a project.
  • Element names must be unique within a block.
  • Variations of a block―say, a search box with a dark background―should add a modifier to the class name.
  • Block names and element names are usually separated by a double underscore (.block__element). Block and element names are typically separated from modifier names by a double hyphen (for example, .block--modifier or .block__element--modifier).

    Here’s what BEM looks like using a search form example:

<form class="search"> 
  <div class="search__wrapper"> 
    <label for="s" class="search__label">Search for: </label> 
    <input type="text" id="s" class="search__input"/>
    <button type="submit" class="search__submit">Search</button> 
  </div> 
</form>

A variation of this form with a dark background might use the following markup:

<form class="search search--inverse"> 
  <div class="search__wrapper search__wrapper--inverse"> 
  <label for="s" class="search__label search_label--inverse">
↵Search for: </label> 
  <input type="text" id="s" class="search__input search__input ↵--inverse"> 
  <button type="submit" class="search__submit search__submit-
↵inverse">Search</button> 
  </div> 
</form>

Our CSS might look like this:

.search {
    color: #333;
}
.search--inverse {
    color: #fff;
    background: #333;
}
.search__submit {
    background: #333;
    border: 0;
    color: #fff;
    height: 2rem;
    display: inline-block;
}
.search__submit--inverse {
    color: #333;
    background: #ccc;
}

In both our markup and CSS, search--inverse and search__label--inverse are additional class names. They’re not replacements for search and search__label. Class names are the only type of selector used in a BEM system. Child and descendant selectors may be used, but descendants should also be class names. Element and ID selectors are verboten. This ensures that selector specificity remains low, selectors are without side effects, and CSS is independent of markup patterns. Enforcing block and element name uniqueness also prevents naming collisions, which can become a problem among teams.

There are several advantages to this approach:

  • it’s easy for new team members to read the markup and CSS, and understand its behavior
  • adding more developers increases team productivity
  • consistent naming reduces the possibility of class name collisions and side effects
  • CSS is independent of markup
  • CSS is highly reusable

There’s a lot more to BEM than what can comfortably fit in a section of a chapter. The BEM site describes this methodology in much greater detail, and also features tools and tutorials to get you started. To learn more about the naming convention aspect of BEM, another fantastic resource is Get BEM.

  • wintercounter

    I’ve totally ditched BEM in the favour of CSS modules since the first time I’ve tried. I can write CSS the old school way with simple selectors like: .show, .hide, .active, etc… I don’t have to think about appropriate namings anymore, that was taking most of the time while using BEM.

  • Kenneth Davila

    I can’t believe this “methodology” is still being pushed by people, the naming convention itself is full of silliness.. really double under score????? this__sucks …..

  • Skattabrain

    Maybe I’m not enlightened but I’m not new at this either… I’ve been implementing it on a new project, not my decision, I’m getting used to it… but I don’t like it yet, never mind love it yet. Plus, I like specificity in a lot of cases. I like styling generic components and type, then with a different parent class you can hook into customizing a few of the component style rules with overrides. Sometimes it helps to add 1 modifier class at the top most component’s div… like –active or –open. I’m being told that any nesting is bad and I don’t agree…


    .something.open .someotherthing {}

    Trying to be open and give it a full shot, but I don’t seem to have the problems BEM aims to solve. There is nothing wrong with well organized nesting in a LESS or SASS setup.

    The long names are ugly… it sucks. I feel like I’ve downgraded.

    It’s also really suboptimal if you are using a library like Bootstrap as a base. Goes without saying, but that’s MO.

Recommended
Sponsors
Get the latest in Front-end, once a week, for free.