BEM Visually Explained
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.
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]
.
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.
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 Block
s 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 Element
s within the product card Block
.
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 Element
s 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.
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 otherBlock
s. - 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.