7 Reasons to Use BEM CSS

Peter Ajtai
Solid Digital
Published in
6 min readSep 12, 2018

BEM is a conceptual framework. It forces you to think a certain way about how you group and reuse components when making websites.

Thinking about your site as being composed of reusable blocks solves many problems.

BEM helps you:

  1. Find and write CSS rules in a large project you are seeing for the first time.
  2. Organize rules for media queries and reusable libraries.
  3. Reduce the complexity and nesting of your CSS selectors.
  4. Have a consistent approach to positioning elements on the page.
  5. Have a consistent approach to changing the look of HTML.
  6. Have a consistent approach to composing larger components from smaller components.
  7. Have multiple people work together on large projects.

An Introduction to BEM

The tech team at Yandex helped create BEM. An early post that describes the problems BEM solves was written by Philip Walton, then at AppFolio. BEM has many variants, including one with namespacing for Atomic Design.

The overall concept of BEM is that you divide your page into Blocks. Blocks are made of Elements. Blocks and Elements can have their appearance, behavior, or state changed with Modifiers.

BEM uses class names to group HTML. Their are many naming schemes. The one I like is separating the block name from the element name with two underscores, and separating the element name from the modifier name with two hyphens:

block-name__element-name--modifier-name

Using two underscores and hyphens allows snake case in the block, element, and modifier names.

An important point is that a piece of HTML can be both a block and an element. For example this <div> is 2 blocks and one element:

<div class="carousel card profile__carousel">

1: Finding and Writing CSS Rules

BEM helps you find CSS rules by organizing styles into blocks. This means that the styles for one block and its associated elements and modifiers all go into the same area. This is usually a file or directory.

For example:

<div class="gallery__carousel carousel">

I can tell from the above that I am looking at a div that is an element in a Gallery block. So I will be able to find this div ‘s positioning within the gallery in the gallery.css file. Since this is also a Carousel block, I will be able to find the css for the Carousel block and the internal Carousel Elements in a carousel.css file or some sort of global-blocks.css file.

In certain cases you might have to select an element inside a child block based on the parent block. For example, if you’re using Vue.js components, you might not have access to the child element layout:

<div class="gallery">
<vue-carousel class="gallery__carousel" :imgs="imgs"/>
</div>

In the above example, you would find the styling for the arrows in the carousel in gallery.css:

.gallery__carousel .carousel__arrow {
...

The above is still only two levels deep, and things should not get any deeper.

SCSS

SASS is well suited for structuring BEM rules with the & operator.

.block {
&__element1 {
}
&__element2 {
}
}

2: Organizing Media Queries and Creating libraries

You can additively combine CSS rules for BEMs. To do this we make use of CSS cascading.

For example you might have a standard components library with very basic CSS rules for a button:

standard-library.css
/* standard-library.css */
.button {
font-family: Roboto-Bold;
font-size: 24px;
line-height: 32px;
}

Then you add styling to that button for your specific project:

my-project.css
/* my-project.css */
.button {
background: rgba(65,117,5,0.30);
border: 1px solid #417505;
border-radius: 3px;
color: #417505;
}
.button__circle-icon {
display: none;
}

Then you add styling to that button that’s only visible on larger screens:

my-project.desktop.css
/* my-project.desktop.css - inside a media query */
.button__circle-icon {
display: inline-block;
width: 16px;
height: 16px;
border-radius: 8px;
background-color: #417505;
}

In BEM these are called redefinition levels. Take a look at the illustration here.

The order these are pulled in would be controlled with includes:

@import '../standard-library.css';
@import 'my-project.css';
@import 'my-project.desktop.css';

3: Reducing Complexity

Conceptually BEM organization is much flatter than the DOM tree. A block is only two levels in BEM: The root block and child elements. Even though blocks can be nested inside each other, nested blocks are just elements inside the parent block, so the two level structure is maintained:

<div class="profile">
<ul class="profile__hobbies">
<li class="profile__hobby">
<div class="profile__like like">
<span class="like__count">

So instead of something like .profile > ul > li > .like you have .profile__like . We know this rule will be where the profile rules are and not where the like rules are, since the rule is an element in the profile block. On the other hand .like__count will be found where the like rules are.

The class names can get verbose, but that is the payment for flatter and smaller SASS files.

4: Positioning

Blocks should only be aware of positioning inside them. This is helpful for block reuse. Positioning should be done by making the block you want to position an element of the parent block.

<div class="sidebar">
<div class="calendar sidebar__calendar">

The above is positioned with:

.sidebar {
&__calendar {
margin: 8px 24px;
}
}

5: Changing the look of HTML

Modifiers change the look and feel of a block or element:

.cta--big {
width: 100%
}

If you need to modify many elements, or if you can’t get at the element you want to modify (because it’s nested in a block you don’t have control over), you can combine selectors:

.profile--highlight {
.profile__image, .profile__name, .profile__bio {
background-color: yellow;
color: white;
}
}

Above, we don’t want to have to put --highlight on each element of .profile . If profile is a Vue component, then it would not be possible to add classes to the component’s inner elements.

Now let’s take the example of using a .header block in a cat gallery. We want to customize the cta element of the .header in a very specific non reusable way. So, instead of adding a global modifier inside .header , we combine selectors. In other words, we don’t want to put the modifier in header.scss . Instead we put the modifier in cat-gallery.scss .

.header--cat-picture-header {
.header__cta {
width: 302px;
}
}

6: Components

Once you start thinking about building things from blocks and elements, it’s easy to start creating front end components to match this structure. Vue.js is very good for this, due to its one file components. Blocks become components, and their scss goes into the component file.

So something like:

<div class="profile">
<ul class="profile__hobbies">
<li class="profile__hobby">
<div class="profile__like like">
<span class="like__count">
...

Would become:

<vue-profile>
<vue-hobby :hobby="hobby" v-for="hobby in hobbies" />
</vud-profile>

7: Teamwork

Having regular patterns of CSS usage enables many people to work together. Since BEM is helpful in component and design system (library of components) creation, it is helps people work together on big projects.

Conclusion

BEM helps you think systematically about CSS organization. This enables you to work efficiently both alone and in teams.

To take a look at how BEM can be combined with Vue.js, take a look at the vue-bem repo. The example site is here.

--

--