BEM Grandchildren: How To Handle Deeply Nested Elements

BEM Grandchildren: How To Handle Deeply Nested Elements

·

0 min read

Understanding the basic concept of BEM (block, element, and modifier) is a fairly simple concept to grasp.

However, things can start to easily go out of control when elements start to get 3 or 4 layers nested deep within a block.


Bonus: Download a free cheat sheet that will show you how to quickly get started with BEM.


These nested elements are typically known as 'grandchild' elements (as they're nested 2 levels deep).

bem-granchild-image.png

In this article, I'll tackle how to solve these common issues and follow BEM best practices.

Ready? Let's dive in.

Chaining Elements Together - The Typical Grandchild Mistake

Here’s how many people solve for nesting elements within elements with BEM:

<div class=“nav”>
    <ul class=“nav__menu”>
        <li class=“nav__menu__item”>
            <a class=“nav__menu__item__link”>Home</a>
        </li> 
    </ul>
</div>

Following this method of chaining elements (like this: .nav__menu__item__link) gets out of control pretty quickly.

It makes your class names difficult to read, not to mention it'll unnecessarily bloat your HTML and CSS files.

This approach also follows the structure of the DOM, which limits your flexibility if the structure of your HTML changes.

Don't just take my word for it. Vladimir Grinenko is on the Yandex team (the creators of the BEM methodology) and said this:

"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

For example, imagine that you realised that you needed to add a <div> inside the <nav>:

<div class=“nav”>
    <div class="nav__wrapper"> <!-- Here is my new div-->
        <!-- Now I need to refactor all the classes below
        because of the new div -->
        <ul class=“nav__wrapper__menu”>
            <li class=“nav__wrapper__menu__item”>
                <a class=“nav__wrapper____menu__item__link”>Home</a>
            </li> 
        </ul>
    <div>
</div>

All the classes within the <div> would need to be updated, as well as updating the class names in your CSS file.

So as you can see, taking the Block__Element__Element__Element is not a long term, sustainable choice.

Here's how to better solve it:

The Grandchild Solution

Instead of chaining elements like nav__menu__item__link, simply focus on the block name itself and use that as the main anchor:

<div class=“nav”>
    <ul class=“nav__menu”>
        <li class=“nav__item”>
            <a class=“nav__link”>Home</a>
        </li> 
    </ul>
</div>

Taking this approach also makes your code much more readable for other developers, as they can easily see all the elements that have a relationship with the block (in this case: .nav).

And if you need to add or remove HTML elements in the future, no refactoring is required:

<div class=“nav”>
    <!-- New div added without the need to refactor -->
    <div class="nav__wrapper"> 
        <ul class=“nav__menu”>
            <li class=“nav__item”>
                <a class=“nav__link”>Home</a>
            </li> 
        </ul>
    </div>
</div>

If you find yourself entering territory where your elements are more than 3 levels deep, you might need to reconsider the structure of the block, potentially even breaking the block into smaller chunks.

And that's it!

I hope this article has helped you solve the 'Grandchild' scenario moving forward.


Download Free BEM Cheat Sheet

Want to start practicing BEM and looking for a no-nonsense, quick start action guide?

Download a free cheat sheet covering BEM basics so you can dive in and start practicing today.