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__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.
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.
This is one of the easiest ways to mark it up. It’s a
item-title element that defines the whole
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
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.
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.