DEV Community

Tom Ray
Tom Ray

Posted on • Originally published at scalablecss.com

BEM Methodology In CSS: A Quick Start Guide

This is a quick start guide to learning BEM, the component-driven CSS methodology.

If you want to start practicing and applying BEM to your projects, this guide will help you get started.


Bonus: Download a free cheat sheet that will show you how to quickly get started with BEM.


Ready? Let's dive in:

BEM Overview

BEM (Block-Element-Modifier) is a CSS naming convention developed by the team at Yandex to improve scalability and maintainability in web development.

Put simply, the idea of BEM is to "divide the user interface into independent blocks" by naming CSS classes in the following methodology:

/* Block component */
.card {}

/* Elements are dependent on their parent block */ 
.card__img {}

/* Modifiers are for incremental style changes */
.card--dark {} 
.card__img--large {}
Enter fullscreen mode Exit fullscreen mode
  1. Block: an independent component that can be reused (e.g. with class name .nav)
  2. Element: a child within a block that cannot be used separately from that block (e.g. with class name .nav__item)
  3. Modifier: a variation in the style of either a block or modifier (e.g. with class name .nav--dark)

Let's dive into some real CSS examples to get a hang of this thing.

Blocks

Blocks are reusable components. Like buttons, cards or form fields.

When naming your blocks, focus on describing its purpose (i.e. what it is) rather than its state (i.e. what it looks like).

For example, .btn or .nav follows the correct naming convention for a block.

.big or .bright-pink describes how it looks, so doesn't scale well when you want to change the design later on.

<!-- INCORRECT -->

<div class="large-red-box">
 <img src="...">
 <h2>...</h2>
 <p>...</p>
 <a>...</a>
</div>

<style>
 .large-red-box {}
</style>
Enter fullscreen mode Exit fullscreen mode
<!-- CORRECT -->

<div class="card">
 <img src="...">
 <h2>...</h2>
 <p>...</p>
 <a>...</a>
</div>

<style>
 .card {}
</style>
Enter fullscreen mode Exit fullscreen mode

If you're wondering how to place blocks within blocks (for example, a button inside a nav), here's a short article to help you with that.

Elements

Inside blocks are where elements live. Elements are dependent on their parent block, and so cannot be used without them.

Elements also have a unique CSS class naming convention which works like this:

.block__element

For example, using the .card component, an element inside the card component (like an image) would have a class name like .card__img.

The element name always appends the block name, separated by a double underscore __.

<!-- INCORRECT -->

<div class="card">
 <img src="...">
 <h2>...</h2>
 <p>...</p>
 <a>...</a>
</div>

<style>
 .card {}
 .card img {}
 .card h2 {}
 .card p {}
 .card a {}
</style>
Enter fullscreen mode Exit fullscreen mode
<!-- CORRECT -->

<div class="card">
 <img class="card__img" src="...">
 <h2 class="card__title" >...</h2>
 <p class="card__description" >...</p>
 <a class="card__button">...</a>
</div>

<style>
 .card {}
 .card__img {}
 .card__title {}
 .card__description {}
</style>
Enter fullscreen mode Exit fullscreen mode

It's important to note that the second code snippet avoids using more than 1 selector to target the styles (e.g. like .card img {}).

It's considered best practice to use a BEM element class and use that directly instead (like .card__img {}).

Following this approach reduces the chance of cascade issues down the line.

Modifiers

When you have varying styles in blocks (or elements), that's where modifiers come in.

For example, your 'card' block might have a light and dark version. Or you might have primary and secondary buttons.

Modifiers have a unique CSS naming convention which works like this:

block--modifier or block__element--modifier.

That's right- BEM modifiers can be applied to both blocks and elements.

Let's dive into some bad and good practices:

<!-- INCORRECT -->

<div class="card--dark">
 <img src="...">
 <h2 class="card__title--large">...</h2>
 <p>...</p>
 <a>...</a>
</div>

<style>
 .card--dark {}
 .card__title--large {}
</style>
Enter fullscreen mode Exit fullscreen mode

It's considered bad practice to use a modifier class in isolation (i.e. without the block or element class).

That's because the modifier is meant to add incremental style changes to the block.

Therefore, whenever using a modifier, ensure it's used with the base class:

<!-- CORRECT -->

<div class="card card--dark">
 <img src="...">
 <h2 class="card__title card__title--large">...</h2>
 <p>...</p>
 <a>...</a>
</div>

<style>
 .card {}
 .card--dark {}
 .card__title {}
 .card__title--large {}
</style>
Enter fullscreen mode Exit fullscreen mode

And that's it!

Those are the fundamentals to get you off and running with BEM.

If you're interested to learn more about the 'why' behind BEM, I recommend checking out this CSS Tricks article.

Like learning anything new, practicing is key. Give BEM a shot in your next project and see where it takes you!


Download Free BEM Cheat Sheet

Want to start practicing BEM and looking for a no-nonsense, quick start action guide?

Download a free cheat sheet covering BEM basics so you can dive in and start practicing today.


Top comments (6)

Collapse
 
codypearce profile image
Cody Pearce

Nice guide! How would you handle components that have more levels of elements? For example,

card
  card__header
    card__title
    card__subtitle
  card__body
    card__title
 ...etc

Or

card
  card__header
    card__header__title
    card__header__subtitle
  card__body
    card__body__title
 ...etc

Or

card
  card__header
    cardHeader__title
    cardHeader__subtitle
  card__body
    cardBody__title
 ...etc
Collapse
 
bytomray profile image
Tom Ray

Thanks for the question Cody!

Your first solution is recommended BEM best practice, so I would stick with that.

In fact, don't just take my word for it ;). Here's a quote taken from one of the guys who is working on the BEM methodology over at Yandex:

"BEM methodology doesn't recommend to use elements within elements in class names. You don't need to resemble DOM structure in naming. Having one level structure makes refactoring much easier."
— Vladimir Grinenko, Yandex

I actually wrote a full blog post already answering your question:
scalablecss.com/bem-nesting-grandc...

Hope this helps!

Collapse
 
dirtycode1337 profile image
Dirty-Co.de

Your block is card, so last thing wouldn't match, because of cardHeader - writing.

The second way is the way I would go, because it keeps classes "unique" for each element, so a header title and a body title cannot be accidentally switched by the notation like in the first example.

I would finally write that this way:

card
    card__header
        card__header-title
        card__header-subtitle
    card__body
        card__body-title
        card__body-content 

This would also finally lead to really small SASS code, which I would prefer before CSS ;) :

.card{
    //properties for the whole card block
    &__header{
        &-title{

        }
        &-subtitle{

        }   
    }
    &__body{
        &-title{

        }
        &-content{

        }
    }
}

I don't see a problem in dividing element or block names with a single - for better readability.

Also you could mix up two blocks within a card block here like you have a card block including a header block and a body block, if header and body blocks are logically seperated like:

card
    header
        header__title
        header__subtitle
    body
        body__title
        body__content

But I would use my example before in this case :)

Collapse
 
tomekbuszewski profile image
Tomasz Buszewski

Oh boy, I still remember pitching BEM to my colleagues in 2014. How they laughed.

I really like this approach, as it introduces component thinking. It takes some time to wrap your head around it, but when it clicks, it becomes the only way you write your CSS.

The only problem I always had, was when you want to modify your block and have its children affected:

card card--dark
  card__header
  card__body

This always resulted in two ways:

  • I created a modified version of every element inside;
  • or I stacked the elements (card--dark > .card_header).

I know the first solution is "cleaner", but sometimes it was really too much. What's your take on this?

Collapse
 
atacrawl profile image
Dan Boland

Another great thing about BEM is how it dovetails beautifully with preprocessors’ nesting capabilities.

Collapse
 
bytomray profile image
Tom Ray

It does indeed 😍.