BEM Advice

I'm trying to use BEM in CSS, but I'm not sure how I should name these classes: I have a task element used throughout a block (game) and an input element that appears inside both sub-sections of the game (solution and question screens). How should I name the elements properly? My current structure:
<div class="game">
<div class="game__solution">
<div class="game__task"></div>
<div class="game__solution__input"></div>
</div>
<div class="game__question">
<div class="game__task"></div>
<div class="game__question__input"></div>
</div>
</div>
<div class="game">
<div class="game__solution">
<div class="game__task"></div>
<div class="game__solution__input"></div>
</div>
<div class="game__question">
<div class="game__task"></div>
<div class="game__question__input"></div>
</div>
</div>
I can't just name both of them game__input because they should have different CSS rules. Also, do I have to say game__solution or is it okay to create a nested block (just solution)? How should I write this so that it follows BEM? NOTICE: I just used divs here for a simplified example
23 Replies
Kingpin
Kingpin•3mo ago
BEM = Block Element Modifier. Your input class would be "Block Element Element". That's not correct. It would be game__input If you need a different variant for each you use modifiers like this game__input game__input--solution And game__input game__input--question
Koner
KonerOP•3mo ago
Okay, I get it šŸ‘ But the game has a lot of tags, so it might be confusing to have everything under the same game block, right? But I guess that's how it works.
Kingpin
Kingpin•3mo ago
Make sure you think in components. In a card there might a button component which required a different block, it's just nested inside it.
Koner
KonerOP•3mo ago
1. But I should only "use" new block names if the component is unrelated to its parent, right? This would be wrong?
<div class="game">
<div class="solution">
<div class="solution__input"></div>
</div>
</div>
<div class="game">
<div class="solution">
<div class="solution__input"></div>
</div>
</div>
Because the solution block is not a standalone block but it depends on the game block. So, it should be game__solution to indicate the dependency? 2. And also, is it common practice to simply assign a class name to all HTML elements, even if you don't actually need to style them (Or later you might want to)?
vince
vince•3mo ago
I want to suggest something different. Why BEM? You can simply use semantic elements and assign a parent class. You can add some child classes too if they make sense, but you're nesting BEM classes 2 levels deep and I think that's where it starts to get messy I can't suggest which semantic elements to use because I'm not sure your usecase but what about something like:
div.game
div.solution
div.task
div.input
div.question
div.task
div.input
div.game
div.solution
div.task
div.input
div.question
div.task
div.input
This way you can just target your classes like
.game > .solution :is(.task, .input) {}
.game > .question :is(.task, .input) {}
.game > .solution :is(.task, .input) {}
.game > .question :is(.task, .input) {}
See how much simpler that is? If you used semantic elements for .task and .input you wouldn't even need class names for those either (unless you're using reusable styles)
.game > .solution :is(div, input) {}
.game > .solution :is(div, input) {}
Though I will say something contradictory. You probably should assign a class name to those nested .solution elements because it's a bit easier to understand what they are. E.g having a div vs. having a div with class name .task tells me what it is, and then target that class name in the selector. My 2cents Another question to ask too is do you even need separate class names or selectors for these? Are you applying specific styles for the tasks inside .solution vs. .question? Or will all .tasks and .inputs be styled the same? No Adding a class to an element which does nothing is confusing to yourself and other developers when they inspect the markup in the DOM. I actively avoid / remove any unused classes in my HTML & CSS when I spot them
Kingpin
Kingpin•3mo ago
That's a lot more complex then using BEM for example.
vince
vince•3mo ago
How? :is() is just a way to select multiple elements in one line. You can separate them out if that's what is making it more complex:
.game > .solution .task,
.game > .solution .input {}
.game > .solution .task,
.game > .solution .input {}
This is equivalent
Kingpin
Kingpin•3mo ago
That's more complex then just writting game__input tho. You'd be writting like this
.game {
&__input{}
}
.game {
&__input{}
}
I am not saying that your solution is a complex solution but it's more complex then just writting the classnames.
vince
vince•3mo ago
I don't agree, I think it's more complex to think of how to write the correct class names using BEM than to just keep it simple (and it's proving my point by the fact that they created a post for this)
Kingpin
Kingpin•3mo ago
They would have created a post for selectors as well if they where using that...
vince
vince•3mo ago
How so?
Kingpin
Kingpin•3mo ago
BEM isn't that hard, neither is your solution.
Koner
KonerOP•3mo ago
To better understand BEM, I came across a list of real-world websites that use BEM (https://github.com/benbrehaut/bem-examples). I have a question about one of the websites (see image): Why is there a wrapper block inside a page-head block, and the wrapper block contains a page-head__text? Because page-head__text should only be a child of its own block page-head and not wrapper?
No description
Kingpin
Kingpin•3mo ago
Idk, but you can have object classes that act as containers around elements.
Koner
KonerOP•3mo ago
So it's okay to have utility/object classes (that's the same right?) in a block but something like this would be not allowed:
.page-head
ā”œā”€ā”€ .wrapper
│ ā”œā”€ā”€ .page-head__text
│ └── .wrapper__gap
.page-head
ā”œā”€ā”€ .wrapper
│ ā”œā”€ā”€ .page-head__text
│ └── .wrapper__gap
Kingpin
Kingpin•3mo ago
Utility and object classes aren't the same.
Kevin Powell
Kevin Powell•3mo ago
yeah, one of the biggest mistakes people make with BEM is thinking every child has to be part of that block, but it doesn't. I see this all the time:
<div class="card">
<h2 class="card__title"></h2>
<p class="card__body"></p>
<a class="card__button"></a>
</div>
<div class="card">
<h2 class="card__title"></h2>
<p class="card__body"></p>
<a class="card__button"></a>
</div>
Chances are, that button looks the same as all the other buttons on your site, so it can just be a .button. That's just a block that happens to be living in another block. wrappers are a great example of this too.
Kingpin
Kingpin•3mo ago
I like to do just .c-btn I like it short. This is why developers should have some understanding how design works, cuz in design especially in figma they work in components. I usually use a different block class when there is a new component that I use in figma. With that card example you can even do easier if you know you gonna have just 1 h2 and a p tag you don't even need the class there and use the tag directly nested like this.
.c-card {
h2 {}
p {}
}
.c-card {
h2 {}
p {}
}
It keeps the html cleaner. And it will only style the h2 and p within the c-card.
Koner
KonerOP•3mo ago
I thought one point of BEM was to give h2 and p a class for future-proofing too?
Kevin Powell
Kevin Powell•3mo ago
it is, nesting like that wouldn't be how you'd work with BEM, if you are going that way. There are advantages to having classes for things like the heading, since the heading level can change. There are ways to write CSS that can deal with that as well... a lot of it comes down to how much time you want to spend making the css more robust, vs just using the right classes where you need them.
StefanH
StefanH•3mo ago
Encapsulating new components early also saves you from insanely deep and rigid classes like card__header__row1__author__avatar__online-status Chances are that avatar can be reused else where so it should be its own component and so on
Kingpin
Kingpin•3mo ago
That's bad BEM Ah that's what you said
StefanH
StefanH•3mo ago
Yes lol

Did you find this page helpful?