DEV Community

Angela Damaso
Angela Damaso

Posted on

Friends with BEM-efits

An Introduction to BEM

What is BEM?

The Block, Element, and Modifier (BEM) methodology is a common naming convention for CSS classes developed by Yandex. The core idea behind BEM is to provide a strict way to arrange your CSS classes into modules. BEM captures the purpose and meaning through it's CSS class name syntax:

  • Block: Represents a module or context where the element finds itself. ("What is it?")
    • navigation
    • footer
    • item-review
  • Element: Describes a component within the block that performs a particular function. ("What does this do/show?")
    • item
    • link
    • button
  • Modifier: Defines the appearance, state, or behavior of a block or element. ("What state is it in?")
    • active
    • red
    • large

We represent this syntax with two underscores for elements and two dashes for modifiers:

.navigation__item--active
.footer__link--red
.item-review__button--large
Enter fullscreen mode Exit fullscreen mode

An Analogy

To grasp a further understanding of how these are all related, think of it like an analogy.

Hierachy

Car
|-- Transmission
|   -- Automatic
|   -- Manual

Person
|-- Female
|   -- Lips
|-- Male
|   -- Beard
Enter fullscreen mode Exit fullscreen mode

CSS

.car {}
.car__transmission {}
.car__transmission--automatic {}
.car__transmission--manual {}

.person {}
.person--male__beard {}
.person--female__lips {}
Enter fullscreen mode Exit fullscreen mode

Let's say we want to display different classes to describe a car's transmission. The block or module would be the Car. The element we are showing is a Transmission, and is modified or described by Automatic and Manual.

In our second example, we see that the modifier is coming before the element!!

If you look at our tree hierarchy, this approach makes more sense. In this example, a Person is being divided into a Female and Male class. Each modifier will have elements of its own, such as Lips or Beard.

Remember to be thoughtful and tasteful when creating your naming hierarchies. Nobody want's to read .person--female__arm__hand--left__finger--pinky and can easily clutter up your markup. If that level of specificity is needed, try breaking it down into submodules for easier readability and organization.

Sass + BEM = <3

In a Sass file, one way to structure your classes is through nesting.

.block {
    &__element {
        &--modifier { 
        }
    }
    &--modifier {
    }
}
Enter fullscreen mode Exit fullscreen mode

which would print out to:

.block__element {}
.block__element--modifier {}
.block--modifier[]
Enter fullscreen mode Exit fullscreen mode

The great thing about this architecture is potential to handle scalability. Code is grouped modularly and describes its purpose and state. Let's take a look at an example:

HTML

<ul class="tabs">
    <li class="tabs__header--active">
        <img class="tabs__content__image" src="">
    </li>
    <li class="tabs__header">
        <img class="tabs__image" src="#">
        <img class="tabs__image--inverse" src="#">
    </li>
</ul>
Enter fullscreen mode Exit fullscreen mode

Sass

.tabs {
    &__header {
        &--active {
        }    
    }
    &__image {
        &--inverse {
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Outputted CSS

.tabs {

}
.tabs__header {

}
.tabs__header--active {

}
.tabs {

}
.tabs__image {

}
.tabs__image--inverse {

}
Enter fullscreen mode Exit fullscreen mode

Pretty cool! As applications grow, this nested structure makes class names easier to read and removes the guesswork when other developers read your code.

Just remember: Try not to nest your Sass more than three levels deep!!

So...Why BEM?

  • Self-documenting CSS! It displays the hierarchy between different nodes' relationships in the DOM.
  • Strict class naming promotes encapsulation and reduce naming collisions or using classes outside a given context.
  • Performance benefits!
  • Tells other developers more about what a piece of markup is doing from its name alone.
  • Removes the need for descendant selectors.
  • Component styles are decoupled and highly portable from project to project. In practice, this means an improvement in code quality and development speed!

In short, BEM will make you push yourself to pay attention to detail, think things through and thus raise the quality of your code :)

Top comments (7)

Collapse
 
mindplay profile image
Rasmus Schultz

Any thoughts on the :where selector in relation to BEM Elements?

It was always the rule to avoid nested selectors - so if you wanted to style (for example) an unordered list, you needed e.g. a .list block and a .list__item element, since a selector like .list > li would create a specificity problem.

With the introduction of :where, it is possible to do e.g. .list > :where(li) without creating a specificity problem, since :where has zero specificity.

Not that this removes the need for BEM Elements - but in cases where semantic child elements can now be used, some components could be much less verbose and more intuitive to use, without creating problems.

I wonder if it's time for an update of the BEM conventions?

Collapse
 
develoger profile image
Develoger

BEM is still very relevant. I really dislike when people say how it is old, without giving details on why one should not use it and what are alternatives in their opinion. Email as technology exist for decades and nobody states something like that!

Anyway, BEM is powerful mainly because of M. Modifiers are what makes the difference IMHO.

One thing I would strongly advise is not to nest Modifiers in SASS nor to nest anything else other than pseudo elements or :hover,:focus...
Nesting makes maintainability hard and if we really write CMP based apps, then not nesting will not cause bloated codebase.

Btw. you have one type on article: .block--modifier[] instead of .block--modifier {}

Will share your article on Twitter, really nice to see people love BEM :)

Collapse
 
reegodev profile image
Matteo Rigon

I've never been able to stand this convention. It surely seems cool but in my opinion it ruins readability.

To me this looks much fluent
.tabs
.tabs-header
.tabs-image.inverse

And then fact that Bootstrap even after completely rewriting v4 didn't adopt BEM makes me think I'm not the only one

Collapse
 
codewithsam profile image
Sanyam Singh

BEM in itself is pretty powerful but as a writer there are 2 things you should talk about too when writing about BEM.
1- what class names the container will have, say we have to wrap our element inside a div and the only purpose of that div is to provide margins and paddings which are not really part of the component. What class name would you choose for that?
2- I would also go little into mixes as they are very powerful and if used properly in BEM it would make things a lot easier.

Collapse
 
junkyjack1 profile image
junkyjack1

BEM is awesome from a few different angles in my opinion.

1) It's great for the development process, having the css structure in line with the code structure is huge.

2) It encourages modularity and organization, making these practices feel very natural. No more "spaghetti styles".

3) It's a well adopted pattern that just works when enforced. Making onboarding much simpler and efficient.

This is all opinion from my experience, but still, I dig it.

Collapse
 
nathanheffley profile image
Nathan Heffley

Shouldn't the img with tabs_image--inverse also have tabs_image since modifiers should only add or override styles from the non-modified version?

Collapse
 
codewithsam profile image
Sanyam Singh • Edited

Same goes with tab_header in active state it should have 2 classes tabsheader & tabs_header--active