Scaling Down The BEM Methodology For Small Projects

Advertisement

Front-end development is no longer about individual frameworks. Tools are available — we merely have to choose. To make the right choices for your project, you need to start with a general approach, or methodology. But most methodologies have been created by big companies? Are they still useful for small companies, or do we need to reinvent them at a small scale?

You probably already know of BEM121, one of those methodologies developed by a big company — namely, Yandex2. BEM posits that three basic entities (blocks, elements and modifiers) are enough to define how to author HTML and CSS, structure code and components, describe interfaces and scale a project up to an industry-leading service.

I’ve spent some time with Yandex and BEM, and I know that this methodology works for large projects. Yandex uses BEM to develop CSS and JavaScript components; Yandex also optimizes templates and tracks dependencies in BEM, develops BEM utilities, supports code experiments and researches the field. On a large scale, this investment pays off and allows Yandex to develop hundreds of its services faster.

Would smaller teams benefit from BEM? I wasn’t sure. BEM is a layer of abstraction, offered with other tools and technologies. A small agile team switching to a full BEM stack would be questionable. Could the idea — the approach itself — be useful?

To make the right choices for your project, start with a general approach, or methodology.
To make the right choices for your project, start with a general approach or methodology.

I had to revisit this question when my career recently took me from Yandex to Deltamethod, a mid-sized startup in Berlin. Facing ambitious development plans, we decided to try BEM on a smaller scale. We wanted the same benefits that Yandex gets from BEM: code sharing, a live style guide, scalability, faster development. We also wanted to keep our toolchain and upgrade the existing code base gradually, rather than start from scratch.

For some time, we’ve been focusing on architecture and the basics, trying aspects of BEM one by one, assessing the results, then moving forward. We keep writing down ideas, guidelines, useful tips and short tutorials. I am now convinced that BEM applies to small projects as well. I’ve written down my findings, in case you find them useful. Let’s start by reviewing the basics.

BEM 101

While semantics is considered the foundation of web development, various front-end technologies do not share the same semantic model. The HTML of a modern app is mostly a div soup. CSS by itself does not offer any structured model at all. High-level JavaScript components use abstractions that are not consistently tied to styles or markup. At the UX level, interfaces are described in terms that have nothing in common with technical implementations. Enter BEM, a unified semantic model for markup, styles, code and UX. Let’s take a closer look.

Blocks

A block is an independent entity with its own meaning that represents a piece of interface on a page.

Examples of blocks include:

  • a heading,
  • a button,
  • a navigation menu.

To define a block, you’d give it a unique name and specify its semantics. Several instances of the same block definition (such as various buttons or multiple menus) might exist in the interface.

Any web interface can be represented as a hierarchical collection of blocks. The simplest representation is the HTML structure itself (tags as blocks), but that is semantically useless because HTML was designed for structured text, not web apps.

Elements

An element is a part of a block, tied to it semantically and functionally. It has no meaning outside of the block it belongs to. Not all blocks have elements.

Examples of elements include:

  • a navigation menu (block) that contains menu items;
  • a table (block) that contains rows, cells and headings.

Elements have names, too, and similar elements within a block (such as cells in a grid or items in a list) go by the same name. Elements are semantic entities and not exactly the same as HTML layout; a complex HTML structure could constitute just a single element.

Modifiers

Modifiers are flags set on blocks or elements; they define properties or states. They may be boolean (for example, visible: true or false) or key-value pairs (size: large, medium, small) — somewhat similar to HTML attributes, but not exactly the same. Multiple modifiers are allowed on a single item if they represent different properties.

Blocks and the DOM

How do you work with BEM while still using HTML? You do it by mapping DOM nodes to BEM entities using a naming convention.

BEM uses CSS class names to denote blocks, elements and modifiers. Blocks, elements or modifiers cannot claim any “exclusive ownership” of DOM nodes. One DOM node may host several blocks. A node may be an element within one block and (at the same time) a container for another block.

A DOM node being reused to host more than one BEM entity is called a “BEM mixin.” Please note that this is just a feature of convenience: Only combine things that can be combined — don’t turn a mix into a mess.

The BEM Tree

By consistently marking up a document with BEM entities, from the root block (i.e. <body> or even <html>) down to the innermost blocks, you form a semantic overlay to the DOM’s existing structure. This overlay is called a BEM tree.

The BEM tree gives you the power to manipulate the whole document in BEM terms consistently, focusing on semantics and not on a DOM-specific implementation.

Making Your First Move

You might be thinking, “I’ll give BEM a try. How do I start migrating my project to BEM? Can I do it incrementally?” Sure. Let’s start by defining some blocks. We will only cover semantics; we’ll proceed with specific technologies (like CSS and JavaScript) later on.

As you’ll recall, any standalone thing may be a block. As an example, document headings are blocks. They go without inner elements, but their levels (from top-most down to the innermost) may be defined as key-value modifiers.

If you need more levels later, define more modifiers. I would say that HTML4 got it wrong with <h1> to <h6>. It made different blocks (tags) of what should have been just a modifier property. HTML5 tries to remedy this with sectioning elements, but browser support is lagging.

For example, we get this:

BLOCK heading
MOD level: alpha, beta, gamma

As a second example, web form input controls can be seen as blocks (including buttons). HTML didn’t get it exactly right here either. This time, different things (text inputs, radio buttons, check boxes) were combined under the same <input> tag, while others (seemingly of the same origin) were defined with separate tags (<select> and <textarea>). Other things, such as <label> and the auto-suggestion datalist, should be (optional) elements of these blocks because they bear little to no meaning on their own.

Let’s see if we can fix this:

BLOCK text-input
MOD multiline
MOD disabled
  ELEMENT text-field
  ELEMENT label

The essential feature of a text input is its ability to accept plain text. When we need it to be multiline, nothing changes semantically — that’s why multiline is just a modifier. At the HTML level, this is represented by different markup for technical reasons, which is also fine because we’re only defining semantics, not the implementation. The textfield tag itself is an element, and label is another element; later, we might need other elements, like a status icon, error message placeholder or auto-suggestion.

BLOCK checkbox
  ELEMENT tick-box
  ELEMENT label
BLOCK radio
  ELEMENT radio-button
  ELEMENT label

These two blocks are pretty straightforward. Still, <label> is an element, and “native” <input> tags are elements, too.

BLOCK select
MOD disabled
MOD multiple
  ELEMENT optgroup
  ELEMENT option
    MOD disabled
	MOD selected

Select boxes don’t really need labels, and anything else here is more or less similar to a normal select box control. Technically, we can reuse the existing <select> tag with all of its structure. Note that both the select block and its option element have a disabled modifier. These are different modifiers: The first one disables the whole control, while the second one (being a perfect example of an element modifier) disables just an individual option.

Try to find more examples of blocks in your web projects. Classifying things according to BEM takes some practice. Feel free to share your findings, or ask the BEM team your questions3!

Let Your CSS Speak Out Loud

Perhaps you’ve heard a lot about BEM as a way to optimize CSS and are wondering how it works?

As mentioned, BEM uses CSS class names to store information about blocks, elements and modifiers. With a simple naming convention, BEM teaches your CSS to speak, and it adds meaning that makes it simpler, faster, more scalable and easier to maintain.

BEM Naming Conventions for CSS

Here are the prerequisites:

  • Keep the names of blocks, elements and modifiers short and semantic.
  • Use only Latin letters, dashes and digits.
  • Do not use underscores (_), which are reserved as “separator” characters.

Block containers get a CSS class of a prefix and a block name:

.b-heading
.b-text-input

That b- prefix stands for “block” and is the default in many BEM implementations. You can use your own — just keep it short. Prefixes are optional, but they emulate much-anticipated (and missing!) CSS namespaces.

Element containers within a block get CSS classes consisting of their block class, two underscores and the element’s name:

.b-text-input__label
.b-text-input__text-field

Element names do not reflect the block’s structure. Regardless of nested levels within, it’s always just the block name and the element name (so, never .b-block__elem1__elem2).

Modifiers belong to a block or an element. Their CSS class is the class name of their “owner,” one underscore and a modifier name:

.b-text-input_disabled
.b-select__option_selected

For a “boolean” modifier, this is enough. Some modifiers, however, are key-value pairs with more than one possible value. Use another underscore to separate the values:

.b-heading_level_alpha

Modifier classes are used together with the block and element class, like so:

<div class="b-heading b-heading_level_alpha">BEM</div>

Why Choose BEM CSS Over Other Approaches

One Class to Rule Them All

CSS sometimes depends a lot on the document’s structure — if you change the structure, you break the CSS. With BEM, you can drop tag names and IDs from your CSS completely, using only class names. This mostly frees you from structural dependencies.

Specificity Problems Solved

Big chunks of CSS are hard to maintain because they keep redefining themselves unpredictably.

This issue is called CSS specificity. The original problem is that both tag names and element IDs change selector specificity in such a way that if you rely on inheritance (the most common thing to expect from CSS), then you can only override it with selectors of the same or higher specificity. BEM projects are least affected by this problem. Let’s see why.

Let’s say you have a table with these style rules:

td.data { background-color: white }
td.summary  { background-color: yellow }

However, in another component, you need to redefine the background of a particular cell:

.final-summary { background-color: green }

This wouldn’t work because tag.class always has a higher specificity than just .class.

You would add a tag name to the rule to make it work:

td.final-summary { background-color: green }

Because BEM provides unique class names for most styles, you would depend only on the order of rules.

Bye-Bye Cascade?!

Nested CSS selectors aren’t fast enough in old browsers and can create unintended overrides that break the styles of other elements. Eliminating a lot of the cascade from CSS is possible with BEM. How is this possible, and why is it important? Isn’t the cascade supposed to be there? Isn’t it the “C” in CSS)?

As you know, every BEM CSS class is unique and self-sufficient. It does not depend on tags or IDs, and different blocks never share class names. That’s why you need only a single class name selector to do the following:

  • style a block container,
  • style any block element,
  • add style extras and overrides with a modifier.

This covers most of your styling needs, all with just one class selector. So, it’s mostly about single-class selectors now, and they are extremely fast. To apply a selector, the browser starts with an initial (broader) set of elements (usually determined by the rightmost part of a selector), and then gradually reduces the set by applying other parts until only matching elements remain. The more steps needed, the more time it takes, which is why you can hardly beat single-class selectors for speed.

CSS is rarely a performance bottleneck on small pages, but CSS rules must be reapplied with every document reflow. So, when your project grows, things will get slower at some point. According to usability science, 250 milliseconds is the perception limit for “instant.” The faster your selectors are, the more room you have to manoeuvre to keep that “blazing fast” feeling for your users.

So, no cascade?! Well, almost. In some cases, you might need two class names in a selector — for example, when a block modifier affects individual elements:

.b-text-input_disabled .b-text-input__label {
   display: none;
}

The nice thing is that any rule that redefines this one will likely depend on another modifier (because of the unified semantics!), which means that specificity is still the same and only the rule order matters. Surely, we can invent more cases that require even more cascading (internal element dependencies, nested modifiers, etc.). While the BEM methodology allows for that, you’ll hardly ever need it in real code.

Absolutely Independent Blocks

If blocks depend on each other’s styles, how do we express that in CSS? The answer is, they shouldn’t. Each block must contain all styles necessary for its presentation. The overhead is minimal, but this ensures that you can move blocks freely within a page or even between projects without extra dependencies. Avoid project-wide CSS resets for the same reason.

This is not the case for elements because they are guaranteed to stay within their parent block and, thus, inherit block styles accordingly.

Alternative BEM Naming Conventions

A number of alternative BEM naming conventions exist. Which should we use? BEM’s “official” naming convention for CSS is not the only one possible. Nicolas Gallagher once proposed4 some improvements, and other adopters have, too. One idea is to use attributes to represent modifiers, and CSS prefixes aren’t “standardized” at all.

The biggest advantage of the syntax proposed by the team behind BEM is that it’s the one supported in open-source tools distributed by Yandex, which you might find handy at some point. In the end, the methodology is what matters, not the naming convention; if you decide to use a different convention, just make sure you do it for a reason.

Semantic JavaScript: BEM-Oriented Code

Many publishers and authors view BEM as a naming convention only for CSS, but that brings only half of the benefits to a project. The BEM methodology was designed to fix (i.e. polyfill) non-semantic DOM structures at all levels (HTML, CSS, JavaScript, templates and UX design), similar to how jQuery “fixes” broken DOM APIs. HTML was designed as a text markup language, but we use it to build the most interactive interfaces around. Experimental efforts such as Web Components strive to bring semantics back into our markup and code, but BEM can be used in a full range of browsers now, while retaining compatibility with future approaches, because it does not depend on any particular API or library.

How do you apply the BEM model to JavaScript code? We’ll go through a development paradigm using as little code as possible. It will be really high-level and abstract, but the abstractness will help us to understand the idea more clearly. You’ll notice another term in the heading above: “BEM-oriented code.” Before explaining what’s behind that, let’s go over some ideas that are useful to know when applying BEM to JavaScript.

Learning to Declare

The first step is to embrace a declarative paradigm. Declarative programming is an approach that concentrates on the “what,” not the “how.” Regular expressions, SQL and XSLT are all declarative, and they specify not the control flow, but rather the logic behind it. When doing declarative programming, you’d start by describing a set of conditions, each of them mapped to specific actions.

In BEM, conditions are represented by modifiers, and any action can only happen on a block or element. The code examples in this article will use the i-bem.js framework, written and open-sourced by Yandex, but your favorite framework might be able to do similar or better things because declarative programming is not tied to a specific implementation.

BEM.DOM.decl('b-dropdown', {
   onSetMod: {
      disabled: function(modName, modVal) {
         this.getLabel().setMod('hidden', 'yes');
         if (modVal === 'yes') {
            this.getPopup().hide();
         }
      },

      open: {
         yes: function() {
            this.populateList();
         }
      }
   },
   /* … */

The code snippet above defines actions for two modifiers on a b-dropdown block. These are similar to event handlers, but all states get immediately reflected in the CSS. Modifiers are still stored as class names on the corresponding block and element entities.

Enabling and disabling different key bindings on a b-editor block is another example of how to use modifiers:

BEM.DOM.decl('b-editor', {
   onSetMod: {
      hotkeys: {
         windows: function() {
            this.delMod('theme');
            this.loadKeyMap('windows');
         },
         emacs: function() {
            this.setMod('theme', 'unix');
            this.loadKeyMap('emacs');
            enableEasterEgg();
         }
      }
   },
   onDelMod: {
      hotkeys: function() {
         this.clearKeyMaps();
         this.delMod('theme');
      }
   }
   /* … */

In this example, we see how modifiers bring logic to our transitions in state.

Methods

With a declarative approach, methods are not always “tied” to a component automatically. Instead, they, too, can be declared to belong to some instances under certain circumstances:

BEM.DOM.decl({ name : 'b-popup', modName : 'type', modVal : 'inplace' }, {
   appear: function() {
      // makeYouHappy();
   }
});

This method is defined only for blocks that have the specific type modifier: inplace.

As in classic object-oriented programming, you can extend semantically defined methods by providing even more specific declarations and reuse the original code if necessary. So, both overrides and extensions are possible. For example:

BEM.DOM.decl({'name': 'b-link', 'modName': 'pseudo', 'modVal': 'yes'}, {
   _onClick : function() {
      // runs the basic _onClick defined
      // for all b-link instances
      this.__base.apply(this, arguments);

      // redefine the appearance from within CSS,
      // this code only gives you a semantic basis! 
      this.setMod('status', 'clicked');
   }
});

As specified by this definition, the extended _onClick method runs only on b-link instances with a _pseudo_yes modifier. In all other cases, the “original” method is implemented.

Semantics will slowly migrate from your markup (where it’s not needed anymore) to your code (where it supports modularity and readability, making it easier to work with).

“… Sitting in a (BEM) Tree”

What is the practical use of a declarative approach if it is way too abstract? The idea is to work with a BEM tree, which is semantic and controlled by you, instead of a DOM tree, which is tied to the markup and specifics of implementation:

BEM.DOM.decl('b-checkbox-example', {
   onSetMod: {
      js: {
         inited: function() {
            var checkbox = this.findBlockInside({
               blockName: 'b-form-checkbox',
               modName: 'type',
               modVal: 'my-checkbox'
            });
            this.domElem.append('Checkbox value: ' + checkbox.val());
         }
      }
   }
}
);

Other APIs exist, like this.elem('name') and this.findBlockOutside('b-block'). Instead of providing a complete reference, I’d just highlight BEM trees as the API’s foundation.

Modify Modifiers to Control Controls

The previous section leaves the important subject of application state changes unaddressed. When app states are declared, you need a way to perform transitions. This should be done by operating on a BEM tree, with the help of modifiers. BEM modifiers can be set directly on DOM nodes (as class names), but we cannot effectively monitor that (for technical reasons). Instead, i-bem.js provides a simple API that you can use as inspiration:

// setter
this.setMod(modName, modVal);
// getter
this.getMod(modName);
// check for presence
this.hasMod(modName, modVal);
// toggle
this.toggleMod(modName, modVal);
// remove modifier
this.delMod(modName);

Thus, we can internally hook into the modifier change call and run all of the actions specified for this particular case.

BEM-Oriented Code Explained

Many JavaScript libraries provide enough power to support the BEM methodology without introducing a completely new tool chain. Here’s a check list to see whether the one you’re looking at does so:

  • Embraces a declarative approach
  • Defines your website or app in BEM’s terms
    Can many of the project’s existing entities be “mapped” to blocks, elements and modifier properties?
  • Allows you to drop the DOM tree for the BEM tree
    Regardless of any particular framework API, wipe out as much of the raw DOM interaction as you can, replacing it with BEM’s tree interaction. During this process, some of the nodes you work with will be redefined as blocks or elements; name them, and see how the true semantic structure of your application reveals itself.
  • Uses modifiers to work with state transitions
    Obviously, you shouldn’t define all states with modifiers. Start with the ones that can be expressed in CSS (to hide and reveal elements, to change style based on states, etc.), and clean your code of any direct manipulation of style.

If your framework of choice can do this, then you are all set for BEM-oriented code.

jQuery users could try these lightweight plugins to extend their code with BEM methods:

From A Naming Convention To A Style Guide

If you work a lot with designers, your team would also benefit from a BEM approach. Imagine that you had a style guide created by a Real Designer™. You would usually get it as a PDF file and be able to learn everything about the project’s typefaces, color schemes, interface interaction principles and so on. It serves perfectly as a graphic book that is interesting to look at in your spare time. However, it would be of little to no use to most front-end developers — at the level of code, front-end developers operate with totally different entities.

But what if you and the designer could speak with each other using the same language? Of course, this would require some training, but the benefits are worth it. Your style guide would be an interactive block library, expressed in BEM terms. Such a library would consist of blocks that are ready to be used to build your product.

Once the designer is familiar with BEM’s terms, they can iterate towards designing blocks and elements, instead of “screens.” This will also help them to identify similar UI parts and unify them. Modifiers help to define visual variations (i.e. which apply to all blocks) and states (i.e. for interactive blocks only). The blocks would be granular enough to enable you to make an early estimation of the amount of work that needs to be done. The result is a specification that fully covers all important states that can be reused with other screens or pages.

This eventually allows you to mock up interfaces as wireframes or sketches, because all of the building blocks have already been defined. More importantly, this model maps directly to the code base, because the blocks, elements and modifiers defined by the designer are essentially the same blocks, elements and modifiers that the developer will implement. If you have been using BEM in your project for some time, then certain blocks are probably already available.

The biggest change, however, is closing the gap between screen and code by operating on the same entities in the UI design and development. Like the famous Babel fish, BEM enables you to understand people who have no idea how your code works.

On a bigger team, working on individual blocks is easier because it can be done in parallel, and big features do not end up being owned by any one developer. Instead, you share the code and help each other. The more you align the JavaScript HTML and CSS with BEM, the less time you need to become familiar with new code.

BEM As High-Level Documentation

Despite all advice, developers still don’t write enough documentation. Moving projects between developers and teams is non-trivial. Code maintenance is all about minimizing the time a developer needs to grasp a component’s structure.

Documentation helps a lot, but let’s be honest, it usually doesn’t exist. When it does exist, it usually covers methods, properties and APIs, but hardly anything about the flow of components, states or transitions. With minimally structured BEM-oriented code, you will immediately see the following:

  • the elements you’re dealing with,
  • other blocks you depend on,
  • states (modifiers) that you need to be aware of or support,
  • element modifiers for fine-grained control.

Explaining with examples is easier. What would you say about the following block?

b-popup
  _hidden
  _size _big
        _medium
	_large
  _dir _left
       _right
	_top
	_bottom
  _color-scheme _dark
                _light

	__anchor-node
	__popup-box
	__close-btn
	__controls
	__ok
	__cancel

By now, you can tell me what this block is about!

Remember, you’ve seen zero documentation. This block could be a structure that you’ve defined in a CSS preprocessor or a YAML meta description.

BEM And File Structure

In a growing project, an inconsistent file structure could slow you down. The structure will only become more complex and less flexible with time. Unfortunately, tools and frameworks do not solve the problem because they either deal with their own internal data or offer no specific structure at all. You and only you must define a structure for the project. Here, BEM can help as well.

Block Library

A block’s folder is the basis of all BEM-based file structures. Block names are unique within the project, as are folder names. Because blocks do not define any hierarchies, keep block folders as a flat structure:

/blocks
  /b-button
  /b-heading
  /b-flyout
  /b-menu
  /b-text-field

Libraries and other dependencies may be defined as blocks, too. For example:

/blocks
  …
  /b-jquery
  /b-model

Inside each folder, the easiest arrangement would be to give each “technology” a distinct file:

/b-menu
  b-menu.js
  b-menu.css
  b-menu.tpl

A more advanced approach would be to store some definitions of elements and modifiers in separate subfolders and then implement in a modular way:

/b-menu
  /__item
	b-menu__item.css
	b-menu__item.tpl
  /_horizontal
    b-menu_horizontal.css
  /_theme
    /_dark
	  b-menu_theme_dark.css
	/_light
	  b-menu_theme_light.css

  b-menu.css
  b-menu.js
  b-menu.tpl

This gives you control, but it also requires more time and effort to support the structure. The choice is yours.

Redefinition Levels

What if you need to extend the styles and functionality of components or share code between projects without changing (or copying and pasting) the original source?

Big web apps, sections and pages could be significantly different, as could be the blocks they use. At the same time, a shared block library often has to be extended, individual items redefined and new items added. BEM addresses this with the concept of redefinition levels. As long as you’ve chosen a file structure, it should be the same for any block. That’s why several block libraries can be on different levels of an application.

For example, you could have a common block library as well as several specific libraries for individual pages:

/common
  /blocks
    /b-heading
	/b-menu
	…

/pages
  /intro
    /blocks
	  /b-heading
	    b-heading_decorated.css
	  /b-demo
	  /b-wizard
	  …

Now, /common/blocks will aggregate blocks used across the whole app.

For each page (as for /pages/intro in our example), we define a new redefinition level: A specific library, /pages/intro/blocks, adds new blocks and extends some common ones (see the extra _decorated modifier for the common b-heading block).

Your build tool can use these levels to provide page-specific builds.

Separation of libraries can be based on the form factors of devices:

/common.blocks
/desktop.blocks
/mobile.blocks

The common library stays “on top,” while the mobile or desktop block bundle extends it, being the next redefinition level. The same mechanism applies when several different projects need to share blocks or when a cross-project common block library exists to unify the design and behavior across several services.

The Build Process

We’ve ended up with many small files, which is good for development but a disaster for production! In the end, we want all of the stuff to be loaded in several big chunks. So, we need a build process.

Yandex has an open-source build tool, Borschik7, which is capable of building JavaScript and CSS files and then compressing and optimizing them with external tools, such as UglifyJS8 and CSS Optimizer9. Tools like RequireJS10 can also facilitate the building process, taking care of dependency tracking.

For a more comprehensive approach, have a look at bem-tools11.

The clearest lesson I’ve learned from BEM is not to be afraid of granularity, as long as you know how to build the whole picture.

Beyond Frameworks

For a while, I was pretty skeptical that BEM is suitable for small projects. My recent experience in a startup environment proved me wrong. BEM is not just for big companies. It works for everyone by bringing unified semantics across all of the front-end technologies that you use.

But that is not the biggest impact of the BEM methodology on my projects. BEM enables you to see beyond frameworks. I remember times when people seriously discussed the best ways to bind event handlers to elements, and when DOM libraries competed for world dominance, and when frameworks were the next big buzz. Today, we can no longer depend on a single framework, and BEM takes the next step by providing a design foundation, giving us a lot of freedom to implement.

Visit the BEM121 website for extra resources, GitHub links, downloads and articles.

Long story short, BEM it!

(al, il)

Footnotes

  1. 1 http://bem.info
  2. 2 http://yandex.com
  3. 3 mailto:info@bem.info
  4. 4 http://nicolasgallagher.com/about-html-semantics-front-end-architecture/
  5. 5 http://xslc.org/jquery-bem/
  6. 6 http://github.com/ingdir/jquery-bemhelpers/
  7. 7 http://bem.info/articles/borschik
  8. 8 https://github.com/mishoo/UglifyJS
  9. 9 https://github.com/css/csso
  10. 10 http://requirejs.org
  11. 11 http://bem.info/tools/bem/
  12. 12 http://bem.info

↑ Back to topShare on Twitter

Maxim Shirshin is a professional front-end developer with 10+ years of experience with complex web-based services and products for desktop and mobile. For the last several years, Maxim has been working on various Yandex services such as Yandex home page and Yandex.Direct. He recently relocated to Berlin where he works as a front-end team lead at Deltamethod GmbH. Maxim remains a consultant with Yandex and keeps himself involved with the BEM community.

Advertising
  1. 1

    I’m thinking to use BEM with Bootstrap and angular js. I don’t know it’ll work or not. so i want to know will that work? Thank you in advance.

    1
    • 2

      It should work but it sounds like unnecessary complexity on top of Angular and Bootstrap.

      4
    • 3

      Vladimir Grinenko

      July 17, 2014 11:01 pm

      To use visual part of Bootstrap with BEM it should be enough to convert source class naming according to BEM naming convention and put all the technologies in which blocks are implemented into same folder. And going that deep there’s no differences on how to connect such blocks with Angular.

      Consider BEM as a way to use Web Components without introducing any new techs just by following some conventions.
      BEM blocks in comparison with components offered in Bootstrap library provide consistent way to hide internal structure (elements) just with the help of namespace. You don’t have to wait until Shadow DOM get wider browser support. Same with modifiers.

      Also BEM is about putting everything about each block together: CSS, JS, templates, documentation, tests and so on. You don’t need to look into different folders to find parts of a block here and there.

      But that’s just the beginning :)
      BEM is like a pie — it has a lot of layers.

      Using declarative approach in JS and templates BEM gives possibility to separate base block implementation and all the peculiarities needed on particular project or just one page. So you can easily update component library version with just changing version number in bower.json. That’s really that easy!

      4
      • 4

        Rubbish.

        BEM classes are in no way like WebComponents or shadow DOM.

        This: a { color: red !important }
        Will break all your BEM.

        WebComponents are cool because they provide a way to isolate the scope of the CSS rules, BEM doesn’t.

        Plus, as I mentioned before even Yandex doesn’t use BEM the way it was intended to be. Just look at their homepage – NOTHING is reused.

        0
  2. 5

    Perfect timing! I like the BEM concept and began using it on a project this week since I’ll be collaborating with another developer.

    One disappointment is most information and articles on BEM are about the *methodology* and rarely contain real code and examples. The theory behind BEM is sound, but how does it look in the real world, especially in CSS?

    For instance: I have a `nav` block under a `header` block that I need to style in a specific way. How do I target that `nav`? Traditionally, you would use `.header .nav { /* new styles */ }`. Is that still the proper way to target with BEM? If not, do I add a `nav–header` modifier to the block, or do I give treat the `nav` as a sub-element of the `header` block with `header__nav`?

    Since each block is supposed to be self contained and reusable between projects, pages and sites, how do you handle unique aspects? Do you have a `site.css` that brings all of the blocks styles together and adds unique styles? Do you make modifiers to handle every specific case (left, right, top, bottom, light, dark, accented, sticky, large, small) and include all of that in your styles?

    There seems to be so much potential, but it’s very easy for me to get lost in the methodology without any resolution in the real world.

    5
    • 6

      Some of the questions were not clear to me either when I first learned about BEM a couple of years ago :) I am going to answer only the nav part of your questions.

      The reason that it will never be .header__nav is simple. Your site’s navigation can exist without a header. It can reside in the footer, or in the sidebar, or in the header. Or it may simply be in the center of the page begging you to click it :) Nav’s a block.

      I use the ---notation to define a modifier (sorry, Yandex :) ) and I would (and do) make it .nav--header to make it more specific.

      4
      • 7

        Thanks for the reply. I prefer the -- notation as well, and use __ for elements. Ugly as heck, but makes it much easier to see the distinction.

        @bem_en on Twitter recommended using header__nav, saying “To support encapsulation inner blocks should not know about parents.”

        Regardless of if it’s the site navigation or not, it is a navigation block residing within the header block that requires specific targeting / styling.

        So based on what you’re saying, you should not target any blocks based on their placement (parent blocks)? You have to create specific modifiers for each potential change?

        Which means if the header navigation is horizontal, with a large font, drop downs, and special hover states, you end up with something akin to nav nav--horizontal nav--large nav--dropdown nav--hover-highlight in the class attribute?

        I understand it’s to keep everything modular and I see the value in having those modifiers as reusable pieces, but I’m just not sure where to draw the line.

        0
        • 8

          At first I sort of disliked the syntax too, but it’s not about looks, as you surely know. The fact that more and more sites (companies) start to adopt this technique is saying something, surely. One gets used to it at the end of the day :)

          I guess I’m in no position to argue about the .header__nav suggestion, although if nav in this selector denotes an “inner block” how do we differentiate it from a regular element then? Hm…

          Anyways, I always went by using it as a regular block with modifiers to have a .nav--christmas or something similar. I would target the nav based on the position like I said – .nav--header – only if some particular styling is needed for the header navigation and nowhere else.

          As far as where to draw the line I can only say I agree it’s hard sometimes ) Especially when we deal with foreseeing the future. But I’ve always thought that to create a block means to create something reusable especially if I feel that a particular thing might turn up later in another place. I also once wrote a blog post myself about the definitions of blocks I have. There I describe a way of using BEM to describe some abstract notions as well, not just regular page entities.

          5
  3. 9

    went to yandex.com to check it in the dev tools… the main page markup is a table. tribute to 90s?:D

    0
  4. 11

    BEM is cool, but one sad thing about all this articles, that there is no good, deep examples how to solve more complex designs. When you have responsive design, with deep nested divs, that hard to name as elements?

    How to make a right decision where element is a part of the block, or it should be as a new block + elements inside.

    BEM itself sounds reasonable, but it lacks information, that can be presented to group of developers to convince that we need to use it.

    We have 40+ developers and we want to choose methodology for CSS, from all of them, only BEM seems like a well defined. But when, more questions are asked, than you can find answers. And bem_en twitters seems really ignorant to questions :)

    Where questions about BEM can be asked (russian / english) so they won’t be ignored?

    4
    • 12

      Actually get an answer, seems like they had too many questions, and mine was lost ;) info@bem.info

      0
    • 13

      Yelena Jetpyspayeva

      July 18, 2014 10:45 am

      I manage @bem_en and @bem_ru and try to get 100% questions answered. Some may take hours and days, cause I need to find a developer to consult, but be sure every question is and will be answered. Moreover, we do take questions seriously and offer companies and teams free consultations via info@bem.info. We develop BEM inside Yandex and mostly for Yandex but we opensource everything that is not about Yandex design to give it all to the community. In CIS countries we host BEMups — our own meetups on BEM where people can get together and ask Yandex developers anything, workshops and talks included. We try to contact every international conferences to give talks about BEM and meet developers that uses our technology to help them solve problems cause in such complex thing documentation is not always enough but it’s not that simple to get into schedule of the conferences when you do not have sponsoring budget at hands.. We have English language chat for faster and bigger questions — https://gitter.im/bem/talk and we encourage to join. And we are developing github powered forum that will be live at bem.info for faster and more proper communication. Our team is too small to support worldwide as we want to in our ideal world, but we do our best. If you lack answer, please, do not think you are ignored, point to the question twice. Thank you in advance ^_^

      5
      • 14

        Ok, answer this, why is Yandex not using BEM between their projects? Something they like to boast about a lot.

        Is BEM actually good, or are you just PR’ing the company that way?

        Thanks in advance.

        0
  5. 15

    I’ve adopted a similar approach to BEM for custom blocks above and beyond what a framework such as Bootstrap delivers. If were heading for a set of standards, which makes sense, it also makes sense to adopt widely used standards.

    It’s interesting that BEM is part of an evolution all front-end coders have been going through – toward modular code.

    The take-home from all of this is that each ‘block’ should be able to exist independently of any other containing block.

    The other take-home is the need to figure out what will be a generic ‘block’ and what is a specific feature ‘block’ – and name accordingly.

    De-coupling dependencies is yet another concept – taking the cascade out, as mentioned in the article.

    If you have an h2 element that is black, 18pt and underlined in one section, yet in another, you want the text colour to be red, the temptation will be to use the cascade.

    But how specific is that particular instance? What if we want that red h2 inside a different block where our cascade no longer works?

    There’s a number of methods – give the h2 a class or create a ‘generic’ class that can be used in any parent container of the h2.

    However it’s done, the current thinking is to cut down inheritance (cascade) as much as possible, resulting in re-usable modular blocks or ‘components’

    2
  6. 16

    Bob Donderwinkel

    July 18, 2014 10:20 am

    Very thorough article, thanks. Especially concerning the use of BEM in Javascript.

    I developed a BEM HTML/CSS scaffolding tool using grunt.js. I will try out some BEM Javascript in this as well, check it out: https://github.com/BobD/kabem

    4
  7. 17

    Thank you very much, Maxim. Such well-explained articles are really needed.

    I do have a question, though. Why append the .b- part to a block? .logo is a block, why write it .b-logo explicitly?

    5
    • 18

      Sergey Semashko

      July 26, 2014 1:55 pm

      I have the same question :) Article is very explained, but in the end I expected to see something like “l-” prefix for layouts. It’s not clear why everything should has “b-” prefix if there are no other concepts aside “block” are described?

      0
  8. 19

    Thank you for this instructive article!

    When I read about BEM all examples seems very logical to me. But when it comes to coding questions over questions emerge.

    Here some approaches to a list of block posts with a read-more link:

    1) In this example every element is an element of the block `post`:

    Text

    Text Text Text

    2) But maybe, I want to use the `read-more` links outside post. This could be a BEM solution, although `read-more` itself lacks any styling:

    Text

    Text Text Text

    3) Moreover it could be better to style many “small” classes to be completely independent from a parent block:

    Text

    Text Text Text

    4) And finally, I could just use a single class and use SASS `@extend`, which is not BEM but very flexible, too:

    Text

    Text Text Text

    with

    `.read-more {
    @extend %monospace, %milli;
    &:hover {

    }
    span {

    }
    }’

    I would be very glad, if you could explain, which approach is correct/best.

    Thank you!

    0
    • 20

      I’d say don’t overcomplicate with extends. Have an independent class for the read more link that is completely uncoupled from a specific block.

      I’d class something like this as a generic typography class that could be used in *any* block, rather than being a feature of a *specific* block.

      This is where BEM, imho, can start getting far too overcomplicated, verbose and repetitive.

      0
    • 21

      Seems like all HTML was sanitised from your comment :-(

      Anyway I think I catch the point. And here is my opinions (as BEM co-author). There is no unambiguous answer — every case has it’s own arguments, so you need to balancing it in your concrete cases.

      1) This is the most common way. The only problem is if some elements starts to be too complex or pretend to be used separately from block. In this case you better go to 2).

      2) This is the normal way if you transform element to block with all it’s styles. Рerhaps only better name it like `post-read-more` if it’s really `post`-depended block. Or keep `read-more` if it’s apply not only for `post`.

      3) This is the worst variant. Try to avoid it, because a lot of small blocks will plunge you into the abyss of the physical markup instead of semantic.

      4) That’s quite BEM! You can consider that you have some utility library with blocks (and maybe elements also) which are used as extends. The only problem with such approach is building bundles of styles for additional load to browser at runtime (as we subtract core deps of main page from build of additional bundle basic helpers most probably will excluded from build). Most likely you will never face this problem, so you can never mind.

      1
  9. 22

    Sorry! Same comment again—hopefully with correct coding. I couldn’t edit my previous comment.

    Thank you for this instructive article!

    When I read about BEM all examples seems very logical to me. But when it comes to coding questions over questions emerge.

    Here some approaches to a list of block posts with a read-more link:

    1) In this example every element is an element of the block post:

    <article class="post">

    <p class="post__content">Text</p>

    <p class="post__read-more"><a href="post__read-more__link">Text <span class="post__read-more__title">Text</span> Text</a></p>

    </article>

    2) But maybe, I want to use the read-more links outside post. This could be a BEM solution, although read-more itself lacks any styling:

    <article class="post">

    <p class="post__content">Text</p>

    <p class="read-more"><a href="read-more__link">Text <span class="read-more__title">Text</span> Text </a></p>

    </article>

    3) Moreover it could be better to style many “small” classes to be completely independent from a parent block:

    <article class="post">

    <p class="post__content">Text</p>

    <p><a href="monospace milli link--hover-bold">Text <span class="my-special-title">Text</span> Text </a></p>

    </article>

    4) And finally, I could just use a single class and use SASS @extend, which is not BEM but very flexible, too:

    <article class="post">

    <p class="post__content">Text</p>

    <p><a href="read-more">Text <span>Text</span> Text </a></p>

    </article>

    with

    .read-more {
    @extend %monospace, %milli;
    &:hover {

    }
    span {

    }
    }

    I would be very glad, if you could explain, which approach is correct/best.

    Thank you!

    0
    • 23

      I’d say don’t overcomplicate with extends. Have an independent class for the read more link that is completely uncoupled from a specific block.

      I’d class something like this as a generic typography class that could be used in *any* block, rather than being a feature of a *specific* block.

      This is where BEM, imho, can start getting far too overcomplicated, verbose and repetitive.

      Just stick an independent class on the a href tag – class=”read-more” – and be done with it. Don’t even bother with a class on the span in this instance, just treat it as a child of your a href class.

      0
  10. 24

    WordPress Expert

    July 19, 2014 2:37 pm

    It’s difficult to comprehend being a newbie. I think I’ll have to search for some easier tutorial to understand and master this BEM thing.

    1
    • 25

      Don’t beat yourself up over it – it’s a concept for creating readable, modular, reusable css/html. It also has it’s critics who feel it’s verbosity and over complicated nature is more a hinderance than a help.

      Just take home the idea of re-usable, modular css.

      5
      • 26

        Dragan Filipovic

        July 20, 2014 2:36 pm

        Article gave us deep explanation of BEM and @ Matthew sumed up in one sentence. Thanks.

        1
      • 27

        Please take a look on “Semantic JavaScript: BEM-Oriented Code” section. BEM is not only for CSS ;-)

        1
  11. 28

    I’m curious to know how the BEM methodology handle contents from an external source or for which you can’t assert the class nomenclature will be followed. As an exemple, the content of a blog can be written by different persons which can not realistically be all asked to know and follow BEM. Also the wysiwyg content editors in CMS’s are not BEM compliant so does it mean you have to drop those? I’m also thinking about html generated by tools and libraries which won’t be BEM compliant.

    In general, I am sympathetic to the idea and the goal behind BEM and I can see the utility for it, but it seems to me that the above points are major issues compromising and restricting the scope of the usefulness of this methodology.

    0
    • 29

      I agree with Nicolas B. I find virtually no working environment where the front-end developer has complete control over the structure of the HTML or CSS. Even when I am the sole FED on a project, frameworks, MVCs and back-end developers are always stepping all over the HTML and creating their own blocks and names for classes regardless of how well you try to train them to do it correctly. Time constraints and deadlines mean that you always have to accept and work with whatever output you are given.

      While BEM sounds like a great idea, I just don’t see it being feasible in the real-world, and I’ve worked in every conceivable web development environment for almost 20 years.

      1
  12. 30

    > HTML5 tries to remedy this with sectioning elements, but browser support is lagging.

    I would not call 89% of browser market ‘lagging’. Even MSIE had it since IE9: http://caniuse.com/#feat=html5semantic
    (Unless you need to support IE6-8 still ;)

    0
  13. 31

    The truth is – if you’re only gonna be using BEM for CSS, without all the JavaScript and XML bells and whistles and structuring your entire project to fit into the BEM methodology) – it is COMPLETELY USELESS.

    You’re adding complexity where it doesn’t need to be.

    I’m sick of people who just jump on everything that is ‘advertised’ and start using it without a second thought.

    My message to front-end community: f***ing grow up and start thinking about what you do. And for the love of god – master the basics before jumping into BEM or whatever other “cool” thing there is out there.

    0
  14. 32

    Very useful article!

    0

Leave a Comment

Yay! You've decided to leave a comment. That's fantastic! Please keep in mind that comments are moderated and rel="nofollow" is in use. So, please do not use a spammy keyword or a domain as your name, or else it will be deleted. Let's have a personal and meaningful conversation instead. Thanks for dropping by!

↑ Back to top