Convenient BEM
Greetings. In this article I will tell you how you can change BEM, retaining its best features and getting rid of the worst.
So first let's talk about what's wrong with BEM? Maybe nothing needs to be changed and everything is so good?
BEM is a methodology that allows you to use CSS / HTML / JS many times. It introduces the concepts of block, element, modifier and mix. Starting to use it, you understand that this is exactly what you have been waiting for for many years, it is so convenient, understandable and beautiful! But after some time, such moments in development begin to occur, which can be solved with the help of BEM, but this brings neither pleasure, nor, most important, benefit. What I'm talking about? Let's go through these moments:
1. Disposable units and items
This problem has bothered me so much that it made me write this article.
The concept of a block implies an entity that can and should be reused, but in practice a large number of blocks are created that are used once.
For example, we need to do the following: place the title on the page, followed by the text field and the button for sending input, as shown in the picture:
What will we do in accordance with BEM? There are several options:
- Create a form block and its elements: title, button, text field
- Create separate blocks for each component (button, text field, title), as well as for the form
- ...
Whichever we choose, we have a problem: how to set indents between all these blocks?
If we chose the first option, then we can decide to set indents for form elements, because this is not contrary to the methodology. However, in this case we are destroying the essence of the block: it cannot be reused, since its internal markup will only fit the current situation.
If we chose the second option, then it would be possible to mix some block to the form, and mix the elements of this block to the form components. And, accordingly, for the elements of the newly created block, set indents. And it is here that the problem of one-time blocks manifests itself: they are created for use only in one place! They can no longer be used, because on other pages the components will be located differently.
This problem generates one-time blocks / elements, as well as type modifiers
блок__элемент_size_размер
or блок__элемент_place_место-где-будет-расположен-блок
(for indenting), which, as already mentioned, are used once and clutter up both markup files and the project with their own directories and files. The same applies not only to indents, but also block sizes (for buttons, for example, it often pulls up changes also
line-height
), font sizes, internal indents, etc.2. Long class names
There's not even much to talk about. I don't think anyone likes markup, which looks something like this:
<headerclass="section-header section-header_margin_select-sector"><h2class="section-header__title font font_face_calibri-bold section-header__title_size_select-sectors">
Select a sector, please:
</h2></header>
3. Default or block theme
Suppose we have a button block. It is necessary to stylize it in accordance with the requirements of the design. But in another project there will also be a button class. It will look different, but some of the styles will be the same. What does BEM advise to do? He says to create a theme modifier and set it to all the required elements.
But with this approach we get the following:
<inputtype="text"class="textbox textbox_theme_P2"><buttonclass="button button_theme_P2">Reset</button><buttonclass="button button_theme_P2">Submit</button><buttonclass="button button_theme_P2">Save as draft</button>
This is a code clutter, and this is bad.
Criticize - offer
What do I suggest to correct this disgrace? I propose the following manifesto, which, in fact, is a superstructure above the standard BEM.
Manifest - Improved BEM
P.1 Module layer and page layer
I propose to split the styling into two parts:
The first part is the components layout. This part is written in accordance with all (almost *) BEM rules. It sets styles for reusable blocks, or rather, components, for example, a button, a text field, a title, etc.
The other part is the page layout. It is required to set styles for blocks and elements of a specific page. Accordingly, these blocks / elements will be used once (in any case, on the same page). Here the BEM rules do not apply. It looks like this:
File:
index.css
.___send-button {
margin-bottom: 2px;
font-size: 13px;
}
.___message-textarea {
width: 240px;
height: 300px;
font-size: 14px;
}
File name page layout'a chosen arbitrarily. The main thing is that it corresponds to the essence of the page. All styles start with '___' so that they cannot be confused with classes of standard BEM entities. Also, classes are not tied to BEM entities — their names only reflect what they should be applied to. It is also worth noting that all page layout styles are located in one file, since they belong to the same page.
This separation allows us to solve the first problem, while not harming the main goal of BEM - creating styles / layouts so that they can be reused. These styles will be applied only on one page and will in no way interfere with the styles of components from the components layout. Thus, we get rid of one-time classes, while retaining the ability to reuse blocks and not violating scopes.
It also makes sense to separate the components and page layouts at the directory level.
* except for the rules that are canceled by the following paragraphs of the manifest.
A.2 Long class names
(Experimental, therefore optional item *)
It is proposed to replace part of the standard naming system with the following:
For a block:
class="блок"
(no changes) For a block with a modifier:
class="блок _модификатор"
(appeal through a combined selector .блок._модификатор
) For an element:
class="блок__элемент"
(unchanged) For an element with a modifier:
class="блок__элемент _модификатор"
(appeal through .блок__элемент._модификатор
) This item allows you to get a short code in relation to modifiers. Obviously, why not do the same with the elements.
It is important that the files with styles do not have rules defined for selectors, which consist only of modifiers:
/*Неправильно!!!*/._active {
background-color: #abcdef;
}
* such a naming of modifiers can lead to problems on blocks / elements mixed with other blocks / elements, provided that both entities can have the same modifier. That is, by specifying a modifier for one entity, we set it for all those that are mixed to this node.
P.3 Default values and themes
It's simple. It is proposed to choose a theme by default, but register styles for it not in the block class, which is in the block file, but in the block class, which should be placed in the theme file. For example:
File -
button/button.css
.button {
cursor: pointer;
display: inline-block;
}
File -
button/_theme/button_theme_P2.css
.button_theme_P2,
.button {
border-radius: 3px;
border: 1px solid #f00;
}
Or in accordance with paragraph 2
.button._theme_P2,
.button {
border-radius: 3px;
border: 1px solid #f00;
}
Thus, this topic becomes standard, but you can use it directly if you wish.
Total
This manifesto is designed to solve some problems arising during layout in accordance with BEM. Its main component was the division into components layout and page layout. Although the manifesto looks quite revolutionary, uncanonical and bold, it solves the stated problems. To use it all, in part or not to use it at all - it's up to you, of course.
PS If you are now angrily scrolling the whole page to put a minus, do not forget to write a comment, otherwise your minus will not bring good (