Enhancing modular design with BEM

In front-end development, the discussion over incorporating the Block, Element, Modifier (BEM) methodology is one that can end with developers from within the same company on opposing sides.

(This article first appeared on Graph.uk)

However, we can clearly see that more and more emphasis is now placed on modular design. Modern page layouts more often including multiple, diverse blocks and modern content management system (CMS) platforms that allow you to position any block on any page.

To achieve this modular design, front-end frameworks such as BEM become essential to the development process as they are more robust, more flexible and will future-proof your site.

Additionally, using the BEM naming convention ensures a shared language for your development team that is more informative and meaningful, which especially enhances collaboration across large and distributed development teams.

What is BEM?

For the purposes of this article, we aren’t going to go into depth about how Yandex developed this BEM framework, but you can visit their BEM site to find out detailed information about its key concepts, project building methodology and history.

A brief summary of BEM:

BEM stands for Block, Element, Modifier and it provides a robust convention for naming your CSS classes as independent modules.

There are a few variations of the methodology, but the most common approach is this:

.block {}
.block__element {}
.block__element_modifier {}

A block: represents an object on your website such as a button, a menu, or a search form.

An element: a component within the block that performs a particular function, such as a menu item, or an input field inside a search form.

A modifier: how we represent any variations of a block or element. For example, an additional menu shown above the header, or before the footer might have a different visual style, but it is still a menu.

A short history of BEM

The BEM methodology originated at Yandex in the mid 2000’s. A Russian competitor to Google and Yahoo, Yandex was built out of search, mail and online services, all of which had complex user interface elements.

To make their developers’ work less complicated, and make the portals easier to maintain, Yandex realised the best way forward was to rethink how their pages were being structured.

They started to separate out the various items on their pages into a series of independent modules (including styles, scripts and templates), which they named ‘blocks’, and developed what we know today as BEM.

How BEM enables modular design

With a modular design approach, each element on the page can be separated into a individual component, such as a form button.

The approach is to design all the individual elements together with their variations. For example, this would include all button styles, menu styles, form styles and navigation cards.

A simple analogy that translates well to the BEM methodology can be to think of these elements, like heading or button styles, as ‘atoms’. The ‘atoms’ then come together to form ‘molecules’, which would be items of related content. These then build up to create ‘organisms’, the block of all related content, which are then combined to form templates that essentially make up the pages of a site.

Consider the example of a button. This could be placed on a contact form, within the header of the website, or as a call to action on the hero block.

In BEM, we would name these examples as follows:

.button {}
.button_hero {}
.button_header {}
.button_secondary {}

All button styles laid out above map to the modular design guide and this means that naming conventions map to the design more closely.

Naming BEM components

When it comes to complex projects that utilise large and distributed development teams, a recent article suggests using post-it notes to successfully generate ideas for component names, which will start developing your team’s shared vocabulary when using BEM methodology.

This works by looking at each component and asking everyone to write down a name that they would assign to it. The team should think about the function the component will carry out and avoid any references to its appearance. You need to ask, ‘does the assigned name still make sense if the component is moved to a completely different place from where one individual may be imagining it?’.

Shared vocabulary

Once everyone has contributed a name on a post-it, reveal each and discuss and compare as a team. The benefit of this is that it identifies certain names that appear multiple times. These names are classed as good candidates to use because they indicate a shared vocabulary within your team. Using shared and informative vocabulary means that your team can work more cohesively on the same project.

Different way of thinking

Many front-end developers take the more traditional approach of using inheritance, where styles cascade through the HTML structure.

Simple traditional format:

#content p {
 font-size: 16px;
 color: #333;
}

Complex traditional format:

section .outer #content .course .course-info p {
 font-size: .875em;
 padding: 0 0 20px 5%;
}

While the simple traditional example is understandable, we have seen real world examples of client teams and agency partners passing around the complex traditional format.

Problems with this approach:

  • It makes the CSS complex to understand
  • It relies on CSS inheritance results in unintended consequences
  • The content loses the correct styles when the client places the block on a different page, or inside a different template
  • As a result, CSS hacks are introduced
  • Over time, this results in the CSS becoming a nightmare to maintain
  • If another front-end developer works on the styles at a later date, they might introduce yet another inherited style that allows for the same unintended consequences.

Faster page rendering with BEM

Ensuring your visitors experience a fast-loading site has become more and more important, especially when it comes to large, complex or transactional e-commerce websites. In fact, fast-loading e-commerce websites have been shown to increase more conversion.

Using the BEM methodology helps with this goal because complying with its approach decreases the processing power needed to render and redraw the page. While the performance of modern browsers has improved, keep in mind that some users may be using older browsers, or low powered mobile devices.

Why is this the case?

Whenever a browser renders an HTML page, it loads all styles found in the CSS into a tree of selectors.

Consider the following HTML:

<section class=”related-article”>
 <div>
 <h2>Hello, world!</h2>
 </div>
</section>

You might decide to style this using:

.related-article > div {
 background: #eee;
 border-radius: 10px;
 padding: 10px;
}
.related-article h2 {
 font-size: 20px;
 color: #333;
}

The issue with this approach is that it forces the browser to look through the entire tree of CSS selectors to figure out which should be applied to our ‘div’ and ‘h2’ elements.

The browser matches the CSS rules above from right to left. So, in our example, the browser needs to find each ‘h2’ in the document, then looks at the parent element, or its parent, and so on, all the way to the top of the tree to figure out if there are any ‘h2s’ inside the ‘related articles” section.

Only then can it apply your style.

With BEM , we would structure this as follows:

<section class=”related-article”>
 <div class=”related-artcile__content”>
 <h2 class=”related-article__title”>Hello, world!</h2>
 </div>
</section>

Then style this as:

.related-article__content {
 background: #eee;
 border-radius: 10px;
 padding: 10px;
}
.related-article__title {
 font-size: 20px;
 color: #333;
}

Now, all the browser needs to do is find all the elements in the document with this CSS class and apply it, without checking numerous parents and parents of parents.

As browsers are already written to work in this manner, this approach provides a better performance for the reflow and repaint stages of rendering a page. It is the fastest way for the browser’s engine to apply the CSS and improves user experience.

How to apply BEM concepts

Bloated CSS

In the discussion over whether or not to use the BEM methodology, opponents typically assert that, because every block has a different name, it makes the CSS bloated.

However, we have found that this is not the case as SASS and LESS offer extended modules. This allows us to set up common ‘base styles’, such as matching all font sizes to a standard typescale, and then reference these for different blocks or elements.

Take a look at the below, where we have rendered common ‘base styles’ as .brick__title {…}, .card__title {…}

.brick {
 &__title {
 &:extend(.type all);
 margin-bottom: 10px
 }
}
.card {
 &__title {
 &:extend(.type all);
 }
}

This removes CSS bloat but still adheres to BEM principals, while again enabling us to easily target our brick titles using the .brick__title selector.

Applying concepts to CMS sites

While BEM works for structural markup, you will find that a lot of content ends up being entered directly by your clients via a CMS. To keep things easy, we never expect clients to add CSS classes to their own content.

We have found that modern platforms, such as Medium, introduce output filters that automatically add CSS classes to output HTML. In turn, we have written plugins for Sitecore and Umbraco that add similar tags to our content blocks.

<h3 class=”graf — h3">Help Customers Save Time</h3> 
<p class=”graf — p”>Another important advantage of 
 using predictive search is to save your visitors’ 
 time on typing. <a href=”…” class=”graf — a”> 
 Recent surveys 
 </a> have problem that more and more customers are 
 using devices without a physical keyboard to 
 shop online.</p>

This means our styles become:

.graf — p {
 font-size: .875em;
 padding: 0 0 20px 5%;
}
.graf — p — first {
 font-size: 1.125em;
}

Key benefits of BEM

  • Reduces risk

BEM provides isolated components that support modular design. Using BEM you can develop each a component in isolation with no risk of missing styles or instigating unintended consequences.

  • Helps teams collaborate

BEM provides you with robust CSS conventions that enables everyone to work to the same standards making it better for collaboration, especially when different teams are working on their own blocks.

  • Easier to maintain

BEM allows for phased migration as blocks or templates are updated. Future updates can be done safely, as you know new styles will only target blocks using specified styles.

  • Improves rendering performance

Each element can be targeted by a single CSS selector (e.g. .card__title), which improves rendering performance and works extremely well with Javascript running on the page.