BEM Visually Explained

 |  BEM, CSS

BEM (Block, Element, Modifier) is a methodology for naming CSS styles in a modular and maintainable manner. If you’ve worked on large websites, I’m sure you’ll have come across indecipherable class names and felt the pain of changing a style in one place and that breaking the styling elsewhere on something that seemingly isn’t related. These are issues that BEM will help you to avoid.

In this article, we’re going to use the example of a product card to explain BEM.

Product card showing a toilet roll
Product card example

BEM relies solely on CSS class names to apply styles to HTML so there are no HTML tag or ID selectors. BEM class names can consist of 3 parts [block]__[element]--[modifier].

Structure of BEM class names
Example BEM class name

Block

A Block is a component part of a website that can exist in it’s own right. We’re using a product card as our example Block in this article. Other examples of a Block are a website header & footer, a login form and a check list.

Product card is the Block

Block names are in lowercase and each word is separated by a single dash (-) e.g. check-list and site-header.

When you can, try and name Blocks as generically as possible so they can naturally be reused. In this example, we have a product card but if you had other cards on your website that all follow a similar style and layout, it would be better to have a card Block that could be used for other cards like offer cards and latest product cards etc. For the purposes of this article, we’ll assume that the product card is highly specialised so a generic card Block has purposefully not been used.


Element

An Element is a child aspect of a Block that only exists within that Block. In our product card example, image, title, price and like-button are all examples of Elements within the product card Block.

Image, title, price and the like button are all elements

Element class names all begin with the Block name followed by 2 underscores (__) and the Element name in lowercase with words separated by a dash e.g. product-card__title and site-header__logo-image.

Element common mistake 1 — Element chaining

One thing to note with Elements is they shouldn’t be chained. If we take the example of a shopping list, it has items and each item has a product image. At first glance, you may think the Block is shopping-list, Element 1 is item and Element 2 is product-image but this is wrong as there should only be one Element in the class name.

.shopping-list__item__product-image {
...
}

Instead, the product image should be thought of as an Element within the shopping-list Block and the class name named as such.

.shopping-list__product-image {
...
}

Element common mistake 2 — Element names based on style

Elements should be named based on the “type of thing being displayed” rather than the “styling to be applied”. With our product card, we have a title which is styled larger and in bold text but the Element should not be named based on it’s style.

.product-card__large-bold {
...
}

Some issues with this class name is by just reading it, it’s hard to know where it’s being used and hard to know where it can / should be re-used in future. Also, if this style was being used for the title, the price, the availability and other information in the product card, if a developer changed this class because they wanted a larger font for the title, they will actually increase the font size for all the other elements which may not be their intention.

.product-card__title {
...
}

Block vs Element

With our made up product card example, we’ve created the like-button Element within the product-card Block which implies that we only ever show like buttons in product cards. If that isn’t the case and like buttons can be shown elsewhere on the site, the like button should become it’s own standalone Block.


Modifier

A Modifier can be applied to either a Block or an Element and is used to adjust the default look or behaviour of the Block or Element. With our product card example, the Modifier liked exists and can be applied to both the product card Block and the like-button Element when a product has been liked.

The modifier liked can be applied to the block and to an element

Modifier class names are separated from the Block or Element by 2 dashes (--) and should be in lowercase and words separated by a dash e.g. product-card--unavailable and shopping-list__item--limited-stock.

Modifier classes should always be used in conjunction with original Block or Element class and just override the attributes to be different. It’s also possible to use multiple Modifier class names on the same HTML tag.

<button class="btn--primary">
Download
</button>
<button class="btn btn--primary">
Download
</button>

<button class="btn btn--primary btn--disabled">
Download
</button>

What are the benefits of BEM?

So you’ve got your head around the slightly odd syntax of BEM (once you’ve seen it a few times, it does become very easy to read), and now you’re probably asking why would I use it? Here’s what I think are the clear benefits:

  • Consistent naming of CSS selectors — With a large project being worked on by multiple developers, there’s often different levels of experience and different approaches to CSS. With BEM, every developer should very quickly be able to understand where each CSS class is used and understand how they should name new classes.
  • Less unexpected broken styles — As BEM classes always target a Block, in theory, any style changes related to that block will not affect other Blocks.
  • No class name clashes — With BEM, there shouldn’t be any class name collisions.
  • Any HTML tags can be used — As BEM only uses class names and not tag or ID CSS selectors, we can use any HTML tags we see fit.
  • HTML structure can change without everything breaking — As BEM classes are all discrete and not nested, the structure of our HTML can be however we like and it can be changed over time without breaking due to CSS cascading issues.
  • Promotes modular, component based design — BEM pushes you to think about your site being composed of discrete areas which promotes abstraction and reuse.