Is any BEM entity allowed to modify any other entity?
Specifically, is an element allowed to modify another entity?
Consider the following example, where a modifier positions another block - in this case, we have a close
block for close gadgets on dialogs etc. and a modal
block for modal dialogs:
<div class="modal">
<header class="modal__header">
Title goes here...
<span class="close"></span>
</header>
<section class="modal__body">
Content goes here...
</section>
</div>
The close
block itself doesn't have margin/padding/positioning, because we want it to be reusable in different contexts.
In the context of a modal
, the close
gadget needs to be positioned properly though, and normally I'd just do this:
.modal__header .close {
position: absolute;
right: 7px;
top: 4px;
}
I've been told this goes against BEM, and instead I should add a modal__close
element, and mark it up as:
<div class="modal">
<header class="modal__header">
Title goes here...
<span class="close modal__close"></span>
</header>
<section class="modal__body">
Content goes here...
</section>
</div>
My argument is that the close modal__close
combination is meaningless, because:
- The
modal__close
element doesn't work on it's own - If you forget to add
modal__close
, theclose
gadget will break the design. - The
close
block should always and only occur precisely once in amodal__header
.
In other words, the close modal__close
combination is meaningless since, in the context of a modal, there is no use-case for either close
or modal__close
without the other.
I'm struggling to understand precisely what BEM is - if it's a naming convention and a set of patterns, the way I understand patterns (as a programmer) is as language used to describe what you've implemented; but not as decision-making drivers that should dictate what you implement.
In the same sense, I feel that BEM naming is valuable as a convention for describing the logical relationships between CSS classes - and shouldn't be viewed as a set of rules that dictate how you structure your CSS.
In fact, for this modal example, I'd like to go even simpler and drop the modal elements:
<div class="modal">
<header>
Title goes here...
<span class="close modal__close"></span>
</header>
<section>
Content goes here...
</section>
</div>
And just write CSS like this:
.modal > header {
...
}
.modal > section {
...
}
Again, my argument is that the immediate header
and section
elements of a .modal
are clearly already elements in the HTML sense, and there is no other use-case for header
or section
elements as immediately children of a .modal
except as the header and body elements of that modal.
Overriding these with a modifier, despite the higher specificity, is literally almost the same thing - e.g. this:
.modal--large > header { ... }
Versus this:
.modal--large .modal--header { ... }
I don't understand how either of these is any better or worse, beside the specificity argument, which seems inconsequential here, since you'll need to specify the modifier and target the header element somehow, for any rule that affects anything below it.
In fact, the first option seems like a generally safer choice in a lot of cases, such as, for example, panels within panels:
<div class="panel panel--red">
<header>...</header>
<section>
Some content here, and another panel:
<div class="panel">
...
</div>
</section>
</div>
In this example, I'd like to target .panel--red > section
to make it red - and this won't and should not affect the color of the nested panel inside it.
Contrast this with:
<div class="panel panel--red">
<header class="panel__header">...</header>
<section class="panel__body">
Some content here, and another panel:
<div class="panel">
...
</div>
</section>
</div>
If you target the panel body with a selector like .panel--red .panel__body
to affect the color, this will cascade to any nested panel__body
elements and override their default color, which is not what was intended.
Bottom line: should you think for yourself and implement your CSS as needed - or should you apply BEM patterns slavishly and set aside your own judgment?
Do my examples go against BEM in any way?
@zxqfox I'd love it if you or someone else at Yandex could provide an authorative answer to this ;-)
@mindplay-dk Of course you should always think and decide for yourself.
But at the same time BEM as methodology is a collection of best practices which work just fine on a large number of different projects and proved to be really great.
Getting back to your question. I think almost all the questions you asked are answered on https://en.bem.info/methodology/css/
As for question about
.modal--large > header { ... }
versus.modal--large .modal--header { ... }
there's a third option:.modal--large > .modal--header { ... }
Hello.
Not sure what it means.
modal__close
define the relation betweenmodal
container andclose
container: even your styles says this:position: absolute
,left
,top
.The possible reason we should mark it with element is making
modal
andclose
blocks less related to themselves. E.g. when we want to useclose
in the other place.I guess this topic is literally about amount of connections between components https://en.wikipedia.org/wiki/Strongly_connected_component
It works even in Linux kernel. Each component should be separated. If it has a lot of connections with another components — then these components are strongly connected and works as one monolith.
Same with mixed selectors:
.component1 .component2 { ...styles... }
— this is a bad practice should be replaced with.component1__semantic-thing
or.component2--modified-for-component1
It will break the design of
modal
but not theclose
component. And it's fine.Actually, this means you should make it an element of
modal
and don't need the separateclose
block. It's totally valid to have structure like:.modal > .modal__header > .modal__close
.Modal is a good example why we should not use
header
tag in selectors.Any user generated content with this tag will break the design.
.modal
here works as a namespace and if you don't like this prefix you can take a look at CSS Modules or something similar.Agree with @tadatuta that you can use
>
and other CSS Next feature if need. And I believe it should be.modal__header
;-)Just that it's meaningless on it's own - it doesn't work without
close
.What I meant is, there would be no reason to use a
close
block anywhere else within amodal
- the only expected use is in the header, and it's easy to target that precisely with.modal__header > .close
without adding another class.I have no problem with the naming conventions - my problem is the meaningless verbosity that ensues for a case like this when applying unnecessary patterns slavishly.
It seems that anytime I bring up practical, concrete points, these are dismissed in favor of some theoretical "best practice" or pattern (or some interpretation of either or a combination of those) that provides no additional practical value in the concrete case.
What I'm struggling to discern is whether following BEM naming conventions is enough to say that "we're using BEM".
In other words, what is "BEM" precisely? By the looks of it, it's a naming convention, and a set of patterns, and a big framework comprising many packages for building BEM-compliant components and applications.
People say "BEM", and they apparently mean very different things - many seem to just apply the naming convention, and claim that makes it BEM, even if they follow the patterns and practices only losely or not at all.
The "Methodology" pages talk about file system structures and build systems, scripting conventions, etc. - which makes it very hard to draw the line and explain what exactly we mean by "BEM".
Thus far, every person I've met has entirely their own perception of the scope of "BEM", ranging anywhere between "just a naming convention", up to "apply all of these patterns mechanically".
There is already a lot of disagreement in a team of 3, and if we decide to ask a team of 20 to apply all or part of these conventions, patterns and practices, we have to be extremely clear on what precisely we mean by "BEM".
It's confusing to the point where I'd almost rather recommend we use the BEM naming convention and nothing else, as I'm afraid that 20 people struggling for concensus internally isn't going to help productivity at all.
Oh, right, but even in this case single
.modal__close
class will work much faster. It's usually important for big projects with a lot of client logic and styles.As for me BEM is a set of good practices based on experience. By using subset of them in each project I'm using it. Even if some of practice does not work in some project I still using the rest. So yes, I still do it.
Well, it's hard to say but I guess I can't say more than "Methodology for Web-development" blabla... bla. I don't know a good definition for now.
Yes, I'm strongly agree that this is an important thing and it's breaking the growth. We even tried to split it to BEM Platfrom, BEM Fullstack, BEM Methodology, BEM Frameworks, but if you talking about it now then it's still a problem.
Also there is problem that English-community thinking that BEM is a CSS-related Methodology. I'm just opening BEM page on the Wikipedia and see redirect to CSS there.
And we should accept that the most part of People talks about CSS when pronouncing BEM. It's sad, actually.
Even monorepos are very close architecturally to Compoments based on BEM https://github.com/babel/babel/tree/master/packages/: each components placed in separate directory with a bunch of tests and a readme file. But people won't see this if no one says.
Would be great if you have done this and will share the results. Very interesting, actually.
The most interesting thing is argumentation on these points:
render
method (like in any VDOM realisation) it's great when names of components in JS are equal to CSS "namespaces" (blocks in BEM)If you had hot discussions on another BEM practices — please tell about it too.
I think I can say that we have a internal block library named Lego (because of blocks-bricks) and earlier it was a seasonal fun Lego-flame/blame where we talk a lot in a huge auditory about BEM and how to use it well. For now almost everyone knows how to use elements, modifiers, when to use it, when do not, how to place it on file system and why, etc, etc.
But you are right that it will be hard to teach everyone to use all aspects of BEM properly. It will spend a lot of time and nerves to find compromise between theory, practical implementation, and probably personal feelings. But it is worth it for sure.