Bem Block, Naming & Nesting

BEM block, naming & nesting

There are a number of variants on how to write BEM classes, so be aware that are multiple competing standards. It started as a set of loose guidelines. Since posting this answer, Yandex has significantly overhauled their official standard (it's quite an improvement). The version of BEM I use is based heavily from an article by Nicolas Gallagher.

At this point I use "Atomic OOBEMITLESS", which is really just a way of saying that classes are modular and namespaced, selectors have low specificity, and states may be toggled with classes which allows CSS to be scaled, on top of a CSS preprocessor to make the code more concise and expressive.

All that said, I will be using the following BEM standard:

  • hyphenated class names as blocks:

    foo-bar
  • block name followed by __ followed by hyphenated class names for elements:

    foo-bar__fizz-buzz
  • block or element names followed by -- followed by hyphenated class names for modifiers:

    foo-bar--baz, foo-bar--baz__fizz-buzz, foo-bar__fizz-buzz--qux

BEM short form: block-name__element-name--modifier-name


You have three different blocks in your examples:

  1. sidebar, which has a sidebar__nav element
  2. content, which has a content__nav element
  3. nav, which has nav__item and nav__link elements

The sidebar and content blocks appear to be variations on the same block, and could be represented as .region.region--sidebar and .region.region--content.

The nav block is implicit on the ul element, and you should make it explicit:

<ul class="nav"><!-- could be content__nav or sidebar__nav as well if you choose -->
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
</ul>

Once you've specified that the ul element is a nav block, it makes sense to have the nav block be modified:

<ul class="nav nav--content">
<li class="nav__item nav--content__item"><a href="#" class="nav__link nav--content__link">LINK</a></li>
<li class="nav__item nav--content__item"><a href="#" class="nav__link nav--content__link">LINK</a></li>
</ul>

Once you've set up the CSS classes, styling all nav__item elements is simply:

.nav__item {
...styles here...
}

and overriding those styles for the content nav__item elements is:

.nav--content__item {
...styles here...
}

BEM naming convention for nested tiny parts

BEM is a methodology about reusable blocks. If you see a visual pattern that is repeated in the UI, then you should consider to see it as a block, not an element. Elements are the block details.

For your wireframe, I suggest two blocks: the lineup block is responsible for the global layout:

<ul class="lineup">
<li class="lineup__item"></li>
<li class="lineup__item"></li>

</ul>

In each <li>, there is an instance of a product block:

<article class="product">
<img class="product__img">
<h3 class="product__title">…</h3>
<div class="product__text">…</div>
</article>

If you want to keep your current HTML structure, then you have a mix on <li> markups:

<ul class="lineup">
<li class="lineup__item product">
<img class="product__img">
<h3 class="product__title">…</h3>
<div class="product__text">…</div>
</li>

</ul>

Here the lineup__item CSS class is responsible for positioning the child block product in the parent block linup. A block should not position by itself (it wouldn't be reusable).

Then, your element product__title has two children en and non-en. With BEM, an element cannot be parent of other elements. But it can nest brother elements. You can do:

<h3 class="product__title">
<span class="product__title-en"></span>
<span class="product__title-non-en"></span>
</h3>

In the BEM tree, title, title-en, title-non-en are all child elements of the product block. It is the light solution.

But maybe you'll realize that this kind of dual titles is a visual pattern used outside the product block, or maybe just for clarity, you can decide to make a dual-title block for that.

<h3 class="product__title dual-title">
<span class="dual-title__en"></span>
<span class="dual-title__non-en"></span>
</h3>

Here the CSS class product__title is responsible for positioning the child block dual-title in the parent block product.

CSS BEM, nest child elements or create new block?

“BEM methodology doesn’t recommend to use elements within elements in class names. You don’t need to resemble DOM structure in naming. Having one level structure makes refactoring much easier.” -Vladimir Grinenko, Yandex

Refer to the Grandchild Solution:

Instead of darpi-form__field__label you should just use darpi-form__label.

BEM: Nested Blocks, what is the best approach?

You want to have clean reusable blocks. Ask yourself which part you might want to reuse.

Multi level nesting of blocks are frowned upon. And that's for a good reason. In case of reusability there should only be one block as root reference. Everything below that one block is, from a bem syntactic point of view, simply an element of that block. Not a sub-block, not a sub element, but only an element.

So, BEM doesn't care about your HTML structure. It's much more a question of what purpose a block or an element has.

I can't really tell from your example what the purpose of your nested footers might be, but it looks to me as if you consider the role attribute of your outer footer element as part of BEM-naming. But it's not. Keep in mind the idea of separation of concerns. role="footer" is HTML semantic. You should not use it as BEM naming reference because you might want to change that HTML attribute one day and then your BEM semantic would go up in smoke.

So, here's what I would do.

Let's say you want your outer footer to be the reusable element then you might want to name your classes like this (just as an example):

<footer class="footer" role="footer">
<footer class="footer__textbox">
<div class="footer__text footer__text--left"> <!-- left as modifier -->
<div class="footer__text footer__text--right"> <!-- right as modifier -->
</footer>
</footer>

Now you can take your footer and use it in any appropriate section of the page and anyone reading your code can get grasp an idea about the purpose of this css structure.

Bem nested naming

You don't need any prefixes for card block but I'd rather go with something like this:

.control
.control__panel
.control__results
.card
.card__title
.card__body

So there's two blocks: control with card inside of it.
control has two elements: panel and results. And card has title and body.

If you want to connect card with control you may add a mix with control__card so the final markup will be:

.control
.control__panel
.control__results
.card .control__card
.card__title
.card__body

For more info about such approach please see https://en.bem.info/methodology/css/#mixes

naming BEM sub blocks

I think the logo, main header, and phone fit in the definition of block which is given in BEM website as:

A block is an independent entity, a "building block" of an application. A block can be either simple or compound (containing other blocks).

What you have got is three simple blocks (logo, main_nav, and phone) within a compound block (site_header). It is actually very similar to the HEAD compound block that is given as an example on the BEM methodology definitions page.

So I would write it this way:

<div class="logo">
<a class="logo__link">
<img class="logo__image">
</a>
</div>

<nav class="main_nav">
<ul>
<li class="main_nav__item">
<a class="main_nav__link">Home</a>
</li>
<li class="main_nav__item">
<a class="main_nav__link">About Us</a>
</li>
<li class="main_nav__item">
<a class="main_nav__link">Contact Us</a>
</li>
</ul>
</nav>

<div class="phone">
<p class="phone__number">
555.555.5555
</p>
</div>

If you think that "logo" is way too generic as a name and wouldn't represent the other types of logos in the project feel free to give it a different name like "company_logo".

In terms of styling, BEM suggests using block modifiers and element modifiers to represent their different styles. For example if you wanted to have your phone number in bold, then you can create a class modifier for it in CSS and apply it to your HTML as follows:

.phone__number--bold {
font-weight: bold;
}

<div class="phone">
<p class="phone__number phone__number--bold">
555.555.5555
</p>
</div>

Modifiers are the preferred way over styling blocks within other blocks. So don't do this:

.site_header .phone__number {
font-weight: bold;
}

I think there is one exception to this which is when you want to give "location-dependant styles" to the block inside. Let's say that you want to give a left margin to the "logo" block. Instead of creating a modifier like:

.logo--push_20 {
margin-left: 20px;
}

it is better to follow OOCSS second principle - Separate container and content - and leave the job to the container:

.site_header .logo {
margin-left: 20px;
}

Naming convention nested blocks and elements in BEM in CSS

BEM is very ease to learn and implement. Also there is some point keep in your mind.
1. You should use short name for parent class if you want use modifier later something like this.

<div class="t-topic"><div>

2. choose simple Element name to you can remember it later. like (unit, thumb, list, item).

This your code.

<div class="t-topics">
<div class="container">
<div class="row">
<div class="col-2">
<a class="t-topics__link" href="#">
<img class="t-topics__image" src=""/>
<span class="t-topic__span">Lorem ipsum</span>
</a>
</div>
<div class="col-2">
<a class="t-topics__link" href="#">
<img class="t-topics__image" src=""/>
<span class="t-topic__span">Lorem ipsum</span>
</a>
</div>
</div>
</div>

There Also other way if you want nested block like this

<div class="t-topics">
<div class="container">
<div class="row">
<div class="col-2">
<a class="link t-topics__link" href="#">
<img class="link__image" src=""/>
<img class="link__image link__image--other" src=""/> // Different image
<span class="link__span">Lorem ipsum</span>
</a>
</div>
<div class="col-2">
<a class="t-topics__link" href="#">
<img class="t-topics__image" src=""/>
<span class="t-topic__span">Lorem ipsum</span>
</a>
</div>
</div>
</div>

You can learn more about BEM from this links.

https://www.toptal.com/css/introduction-to-bem-methodology.
https://www.smashingmagazine.com/2012/04/a-new-front-end-methodology-bem/

Guidelines for how deep to nest BEM style class names

You should completely flatten your block structure to use BEM convention.

It might look something like this:

.abc {}
.abc__main {}
.card {}
.card__item {}
.card__heading {}
.card__icon {}
.card__text {}
.card__text--em {}
.card__text--green {}

It's in the FAQ here: http://getbem.com/faq/#css-nested-elements



Related Topics



Leave a reply



Submit