DEV Community

Cover image for What is BEM in CSS?
Salma Alam-Naylor
Salma Alam-Naylor

Posted on • Originally published at whitep4nth3r.com

What is BEM in CSS?

Have you ever worked on an application with one huge CSS file and found that when you changed a style rule in one place, something unexpected happened somewhere else? I had this problem a lot in my early days of front end development. It was frustrating! So what can you do to stop this from happening?

You need to scope your style rules!

To scope your CSS means to encapsulate style rules in a systematic way so that they apply to one particular chunk of HTML only. CSS-in-JS solutions such as Styled Components or CSS modules that ship with front end frameworks have largely solved this problem by scoping styles to your component templates as standard. This means you don't need to worry about classes in one component affecting the styling of another component — even if you use the same class name. Nice!

But what if you're just starting out, and you want to focus on building out pure CSS in a systematic way without getting bogged down with CSS-in-JS?

Working in pure CSS

In order to scope your styles in pure CSS, the aim is to declare your CSS classes specifically and solely for individual HTML components. Style rules should be purposefully verbose and self-documenting, without relying on inheritance or default browser behaviour. This type of system discourages the use of utility classes reused across multiple components because this is where you can run into the problems described at the beginning of the post. If you change the style properties of a utility class used in multiple components, it could affect the layout of your whole application — sometimes with very undesirable results!

Let's take a look at how we can harness the power of a system like BEM.

What does BEM stand for?

BEM stands for block, element, modifier, and it's a super-handy system to help you scope CSS style properties to blocks of HTML. What's more, it encourages you to make your HTML and CSS descriptive and self-documenting — helping identify the purpose and intended function of the CSS classes in the code itself.

Other class naming conventions exist alongside BEM to help you scope styles when writing HTML and CSS — such as OOCSS and SMACSS. You can even roll your own system! But the most important thing to remember is to use a system, stick to that system, and make it work for you.

So, how do we work with BEM?

Block, element, modifier

Let's take a look at the building blocks of BEM.

Block: a chunk of HTML to which you want to scope styles

.block {
}
Enter fullscreen mode Exit fullscreen mode

Element: any element inside that block, namespaced with your block name

.block__elementOne {
}

.block__elementTwo {
}
Enter fullscreen mode Exit fullscreen mode

Modifier: a flag to add styles to an element, without creating a separate CSS class

.block__elementOne--modifier {
}
Enter fullscreen mode Exit fullscreen mode

BEM syntax conventions

  • Use one or two underscores to separate the block name from the element name
  • Use one or two dashes to separate the element name and its modifier
  • Use descriptive class names in camelCase

BEM in context

In context, your HTML using the above class names might look like this:

<section class="block">
  <p class="block__elementOne">This is an element inside a block.</p>
  <p class="block__elementOne block__elementOne--modifier">This is an element inside a block, with a modifier.</p>
</section>
Enter fullscreen mode Exit fullscreen mode

In a real-life example, with more realistic class names, this might look like:

<section class="container">
  <p class="container__paragraph">This is a paragraph inside a container.</p>
  <p class="container__paragraph container__paragraph--bold">
    This is a paragraph inside a container, with a modifier that adds bold styling.
  </p>
</section>
Enter fullscreen mode Exit fullscreen mode

Using the fully-declarative approach, where you don't rely on inheritance or default browser styles, your CSS classes might look like this:

.container {
  display: block;
  margin: 1rem auto;
  padding: 1rem;
  box-sizing: border-box;
}

.container__paragraph {
  color: #000000;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 1rem;
  font-weight: normal;
  line-height: 1.2;
  margin: 0 0 1rem 0;
}

.container__paragraph--bold {
  font-weight: bold;
}
Enter fullscreen mode Exit fullscreen mode

Notice how any default browser behaviour we might take for granted has been declared in the above classes — such as display: block on the .container <div> element. This is an extremely useful way to ensure that if you need to switch up the HTML elements in your components — for example swapping the <div> (default display: block) for a <span> (default display: inline) in the above example — the resulting styles of your components are not affected.

Wrapping up

Using BEM is not going to solve all your CSS problems (good luck with centring those <div> elements in your layouts!), but it can help you take a step in the right direction to make your CSS readable, descriptive, and safe from any unexpected results. Again, the most important thing to remember is to use a system, stick to that system, and make it work for you.

Check out my latest YouTube video that supports this post. Subscribe for more regular front end web development tips!

And remember — build stuff, learn things, love what you do!

Top comments (15)

Collapse
 
metalmikester profile image
Michel Renaud

Funny that just yesterday I was reading a (very controversial) post here on dev.to that mentioned BEM and I was wondering, "argh, what's that again?" as I couldn't remember, but I didn't have time/forgot to look it up. And here we go, first thing this morning, this post. :) Thanks. ;)

Collapse
 
rajeshkumaryadavdotcom profile image
Rajesh Kumar Yadav

I already have this in my project, good to see you explained it very well here, thank you!

Collapse
 
drehere profile image
Andrey • Edited

Bem is the next best thing since css itself. I think originally was developed by smart folks at yandex

Collapse
 
dev_emmy profile image
nshimiye_emmy

wow

Collapse
 
jeffchavez_dev profile image
Jeff Chavez

love this!

Collapse
 
isabellacacelia profile image
Isabella

Nice post!

Collapse
 
owenmelbz profile image
Owen Melbourne • Edited

Ever wondered why your CSS files are 200mb? Ah yes, BEM :P the place where you infinitely add more and more css incase you ever break something as you hate the world of DRY :P [/troll]

Collapse
 
mrsize profile image
Thomas Dufranne • Edited

Hi, I'm wondering, how do you manage the class name for all children elements ?
is this logic is correct ? :
.block_elementOne > .elementOne_head

Collapse
 
whitep4nth3r profile image
Salma Alam-Naylor • Edited

I would usually do this:

.block_elementOne > .block_elementOneHead

However, as usual with web dev, it depends.

If .elementOne could exist as its own ‘block’, then what you have suggested is fine. However, if it’s an intrinsic element of ‘.block’ and shouldn’t exist outside of ‘.block’, then with this system, it should always be prefixed with ‘.block__’.

As people have suggested, class names can get incredibly long with BEM. However there are always trade offs in any system. As the article states – pick a system and make it work for you. ☺️

Collapse
 
mrsize profile image
Thomas Dufranne

You are right, i think the fact that an element can or not exist by itself is a good point to define the class name.
Alright, thanks Salma for the clarification !

Thread Thread
 
whitep4nth3r profile image
Salma Alam-Naylor

Happy to help! ☺️

Collapse
 
socoladaica profile image
Socola Đại Ca • Edited

CSS syntax is mostly case-insensitive, I think we should use kebab-case instead camelCase for descriptive class names

Collapse
 
whitep4nth3r profile image
Salma Alam-Naylor

It’s all personal preference. As the article states, choose a system and make it work for you.

Collapse
 
socoladaica profile image
Socola Đại Ca

I mean Abc aBc abC is same

Collapse
 
sergeyie profile image
Sergey Ieffe

Hmm. Another solution for large css structures like bigger than 1mb.