Getting On Board with BEM

The first time I designed and built a large website, I was dismayed at how quickly my CSS file became a huge, ungainly mess. One front-end methodology would have saved me a lot of pain (and cleaned up my code): BEM (Block Element Modifier), a naming convention for CSS classes.  When you’re just learning to code, using BEM can seem like overkill. But, in a professional setting, BEM (or the alternative methodology of your choice) becomes indispensable for efficiency and clarity of code – especially when paired with SASS (more on that here). I’m a total convert, and thought I’d share some of the lessons learned along the way.    

While BEM is pretty simple once you get the hang of it, its focus on flattening the DOM tree while also describing relationships can feel less than intuitive at first. Below is an overview of BEM basics and some FAQs that I wrestled with as I learned how to look at my code through BEM-colored glasses. Feel free to add your own questions and answers in the comments!

BEMEFITS

BEM isn’t the only naming methodology out there, but it’s the one we use here at Delphic. So, what do we like about it?

  • BEM makes collaboration easy: Diving into another developer’s project or developing a project with a team has its challenges.  People get comfortable in their own naming conventions for CSS selectors, which may be quite different than your own. Using BEM removes this issue. It provides a clear architecture and recognizable terminology for use across projects and among developers.
  • It’s modular: BEM keeps HTML components’ styling independent of each other while still describing their relationships; everything is a class and nothing is nested (with a couple exceptions of course). This makes the code reusable/moveable and avoids specificity issues.
  • It declares its purpose: When we use BEM’s syntax, it’s easy to skim the markup and understand how elements are styled and related to each other.

THE BASICS

BEM describes relationships between the items in our HTML markup.

  • Blocks: Blocks describe a standalone, high-level object on the page – in other words – a page component. Blocks are independent from each other, meaning that they can be placed anywhere on the page, including within other blocks, without affecting other components. Ex: .main-nav or .btn
  • Elements: Elements are items that make up each block and are its children. They depend on their parent block for meaning, and can’t be moved around the page arbitrarily. In a navigation block, each navigation item would be an element. A double underscore links an element to its block. Ex. main-nav__item {}
  • Modifiers: Modifiers are flags on blocks or elements to change appearance or behavior.  A double hyphen links a modifier to its block or element. Let’s say we want the Contact nav item to be styled differently to highlight it.  We could add a class like .main-nav__item--highlight to make those style changes.

Here’s what our HTML might look like for a nav block:


<nav class="main-nav">
<ul class="main-nav__list">
 	<li class="main-nav__item"><a class="main-nav__link" href="#">Home</a></li>
 	<li class="main-nav__item"><a class="main-nav__link" href="#">About</a></li>
 	<li class="main-nav__item main-nav__item--highlight"><a class="main-nav__link" href="#">Contact</a></li>
</ul>
<button class="btn">Subscribe</button>

</nav>

GENERAL RULES

Here are some general principles that help guide BEM methodology.

  • Stay flat: Just because your BEM naming describes blocks’ and elements’ relationships to each other doesn’t mean it’s a literal description of the DOM tree. You should never have a class name describing a grandchild element like this: .block__element__element.
  • Avoid high specificity: One of the values of BEM is that it (mostly) keeps everything at the same level of specificity (no IDs, no use of HTML elements in CSS selectors like .class > ul). Ask yourself, how can I target an element without increasing specificity?
  • Maintain modularity: Always question whether nested blocks are independent of their parent containers. If they are, they can also be named independently of the parent containers.

FAQS

  1. How do I name nested blocks? Let’s take a look at the button block within our nav block described in the Basics section. If this button is styled the same in the nav as it is elsewhere on the website, the naming is very simple. It doesn’t have a dependent relationship to .main-nav (it just happens to be there), so you can still name it .btn.
  2. But what if my nested block has elements in it? How do I name them? If the nested block is still its independent self, you can just name your elements accordingly. If your nested block is still feeling dependent to its parent, checkout question #3.  
  3. How do I name a nested block whose styling is affected by its parent block? Let’s say the button block in the nav has less padding than its out-of-nav counterparts. A simple approach suggested by David Berner is to separate the style changes into a few simple modifiers – something like .btn .btn--small .btn--rounded. Even if you only use these styles for one instance currently, they will be reusable and agnostic of the element’s parent container for later use elsewhere on the site. Another way that your nested block may be affected by its parent block’s style is layout. Maybe you have two nested blocks that by default are 100% width, but are in a 2 column layout in a particular parent block. In this case, it would be best to create a layout/grid wrapper element so that the nested block styling is separated from positioning.
  4. How do I name nested elements? Block html structure should always be flattened.  From a BEM point of view, all elements within a block should be named .block__element1, .block__element2 etc, whether or not they’re nested. This provides the benefit that if element structure is modified within the block, you don’t need to make any changes in the CSS.  
  5. How do I name elements specific to a certain block modifier? If a block has a modifier and its elements also have style changes based on that modifier, this is a rare acceptable case for nested selectors, even though it increases the specificity.  For example: in the block with class .block--modifier, it would be acceptable to target the block’s element like so: .block--modifier .block__item. The benefit of this method, as opposed to .block--modifier__item, is that it allows you to pull in the base styles for .block__item, keeping your code nice and DRY.
  6.  How do I structure BEM in Sass? BEM really shines when you’re using SCSS.  Visually nesting elements and modifiers within the block class name quickly illustrates the relationships between components without actually increasing specificity (except for the nesting described in #5).  
.block
	{
		&__element
		{
			&--modifier {}
		}


		&--modifier 
		{
			.block__element
		}
	}

will become:

.block {}
.block__element {}
.block__element--modifier {}
.block--modifier {}
.block--modifier .block__element

GO FORTH!

There are a ton of resources for further BEM learning, but hopefully this post will help you sort through the basic questions that come up when you’re first adopting the methodology. Happy coding!  

Front-End Friday is an ongoing series about our favorite tools, tricks, lessons, and best practices. Want to share your own favorite front-end development lesson? Chat with us on Twitter!

« Prev Article
Next Article »