BEM elements and their elements

TL;DR

Use a BEM mixin when you have an element that defines an element and not the block. If you don’t know what I’m talking about right now, please read on.


I like BEM’s ideas to divide all entities on a page into Blocks, Elements and Modifiers. It’s a good (and quite opinionated) way of working on any project, be it a large one with lots of developers or small ones with only few people making stuff. Back in April I wrote about BEM blocks and elements with a focus mainly on blocks, now it’s time for another BEM post. Today I am going to describe the way I understand BEM’s elements and will provide a typical website section as an example. So let’s get started :)

Yandex gives us a clear definition of what elements are:

An element is a part of a block that performs a certain function. Elements are context-dependent: they only make sense in the context of the block that they belong to.
Varvara Stepanova, former Yandex front end developer

The key part here IMO is context-dependent, which means that elements sort of define the blocks and cannot live outside of them. But what if an element too has an entity that defines it and not the block? Let me give you an example. Consider a News section on a typical website. It may look as follows:

news section example
News section mockup

A typical markup for such a section will be:

<div class="news">
    <section>
        <h1 class="news__title">News</h1>
        <ol reversed>
            <li class="news__item">…</li>
            <li class="news__item">…</li>
            <li class="news__item">…</li>
        </ol>
    </section>
</div>

So far so good, right? We have a div with a class of news that has a news__title and some news__items. What is left is to code the news__item itself. It has a title too, what class name should we give to this title since news__title is already taken? Actually there are several options here, comparing of which should lead us to understand BEM elements better.

.news__item__title

I’ve seen some people use it, but I personally don’t like it for several reasons. Firstly, it goes against Yandex, so it’s not BEM, but a completely new BEM-like modification, which is absolutely fine of course, if it works for someone. Secondly, it potentially justifies the nesting of elements even further, having .news__item__title__icon thing or any of that sort. Not good to me. Thirdly, it still provides the connection between this title and the whole news section. Although of course it’s possible to have such a class, but let’s see if we can come up with something better.

.news__item-title

This is one of the easiest ways to mark it up. It’s a item-title element that defines the whole news section…

.news__title--item

This variant basically says hey, I’m the news title, but I’m different from the main news title, cause I’m in the item.

I’m not happy with any of the three variants, because they provide a false connection between HTML elements. In all of the three variants the item’s title should define the item itself, not the whole section. In Yandex’s words, they have a context-dependency on the wrong block. So without much further ado, here’s the variant I personally like and find it both BEM compliant and functional :)

<div class="news">
    <section>
        <h1 class="news__title">News</h1>
        <ol reversed>
            <li class="news__item post">
                <h2 class="post__title">Title of news one</h2>
                <img class="post__thumbnail" src="image.jpg" />
                … etc.
            </li>
        </ol>
    </section>
</div>

So, I introduce a new block here, having news__item and post on one DOM element. Yandex calls such entities BEM mixins or mixes. Having a separate block on this node makes the whole post a fully independent and reusable entity.

What also will come in handy is the splitting of styles. We can see that the items in the news section are presented in three columns, a perfect candidate for floating them will be the news__item selector and not the post class. The latter will only contain styles that are independent of the surroundings. Also having post__title really defines the post itself, not the news section, so such classnames really help maintain the BEM relations between nodes and ensure the post block is reusable throughout the site.

Conclusion

I have come up with a rule of thumb. If you have an element inside an element that defines the element itself and not its block, make sure that the ‘first-level’ element is also a block. Go for a BEM mixin :)

Potentially, mixins are the most powerful entities in BEM, unfortunately there are not so many resources (with cooler examples) on them, but I’m sure there will be. My own news__title will of course be a mixin itself in production, I guess it will look something like this: <h2 class="news__title title title--primary">News</h2>

If you have any questions, please, go ahead and leave a comment.

  • Влад Ржевицкий

    Еретик!

  • Hugo Silva

    I think mixins make a lot of sense, but get a little confusing as the project grows. On this example it is easy enough to distinguish between the properties that belong to news__item and post blocks, but I often found myself checking multiple blocks to make sure I am editing a certain property under the correct class. For that reason I prefer to add an extra element to the markup to define a new block, or use inheritance (extend with sass) when it makes sense, like on the title example: I would define news__title only, and have it extending from title and title–primary with sass…

    • Hey Hugo, thanks for the feedback. I agree that having multiple blocks on the same node increases the complexity of debugging it a bit, but the primary purpose for that is to DRY your CSS as well, not just your Sass (LESS) files.

  • Thanks for this. I agree, I’m just about to use a similar construct – and specifically I agree with how cleanly it separates the css rules. The rules for layout among siblings & parent are element rules, and rules for self and anything inside, those are block rules. Traditionally they were just mixed up inside a single CSS class, but this approach causes us to think about the difference, which I think is great.

    One correction, btw, its “BEM mix” (not mixin).

    • Hey Gal, thanks. I’ve always hoped I’m not alone :)))
      The only thing to note that it’s sometimes pretty hard to follow this approach. At least for me.

  • Alessandro Candini

    Thank you so much for this!!!