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:
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__item
s. 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.