Well is the acronym for Block Element Modifier (Element Modifier Block), is a methodology based on these three entities that deifne nomenclature rules, file structure and code writing
Block: A functionally independent page component that can be reused
Element: A part composed of a block that cannot be used separately from it
Modifier: Defines the parency, state or behavior of a block or element
Nomenclature:
The names are written in lowercase Latin letters.
Words are separated by a hyphen (-
).
The block name defines the namespace for its elements and modifiers.
The element name is separated from the block name by a double underscore (__
).
The modifier name is separated from the block name or element by a single underline (_
).
The modifier value is separated from the modifier name by a single underscore (_
).
For boolean modifiers, the value is not included in the name.
There is also alternative nomenclature schemes:
Two stroke style: block-name__elem-name--mod-name--mod-val
Camelcase style: blockName-elemName_modName_modVal
React style: BlockName-ElemName_modName_modVal
Style without namespace: _available
In addition to these, it is permitted to create an own nomenclature according to needs
It defines a file structure based on class nomenclature, separating the different technologies into different files
May have a nested structure:
project
common.blocks # Nível de redefinição com blocos
input # Diretório pro bloco input
_type # Diretório pro modificador input_type
input_type_search.css # Implementação CSS do modificador input_type
__clear # Diretório pro elemento input__clear
_visible # Diretório pro modificador input__clear_visible
input__clear_visible.css # Implementação CSS do modificador input__clear_visible
input__clear.css # Implementação CSS do elemento input__clear
input__clear.js # Implementação JavaScript do elemento input__clear
input.css # Implementação CSS do bloco input
input.js # Implementação JavaScript do bloco input
Flat structure:
project
common.blocks
input_type_search.css # Implementação CSS do modificador input_type_search
input_type_search.js # Implementação JavaScript do modificador input_type_search
input__clear.js # Elemento opcional do bloco input
input.css
input.js
popup.css
popup.js
popup.png
Or flex, which is a mixture of both
project
common.blocks # Nível de redefinição com blocos
input # Diretório pro bloco input
_type # Diretório pro modificador input_type
input_type_search.css # Implementação CSS do modificador input_type
__clear # Diretório pro elemento input__clear
_visible # Diretório pro modificador input__clear_visible
input__clear_visible.css # Implementação CSS do modificador input__clear_visible
input__clear.css # Implementação CSS do elemento input__clear
input__clear.js # Implementação JavaScript do elemento input__clear
input.css # Implementação CSS do bloco input
input.js # Implementação JavaScript do bloco input
popup # Diretório pro bloco popup
popup.css
popup.js
popup.png
As you can see, below the project root directory (project
), there’s another (common.blocks
), this is part of the redefinition levels, the idea is to be able to divide the code into "subprojects", for example, common.blocks
with the core and mobile.blocks
and desktop.blocks
with the specifics of the desktop and mobile interfaces, respectively. Specific files can totally or partially overwrite the classes of core, or until there are no specificities of certain entities
Certain Patterns design acquaintances ...
Principle of single responsibility: A class must have one and only one responsibility, that is, a modifier class .button_red
should only change the style of the button to red, should not change its position, state or other feature that is not closely related to its main purpose (red style)
Open-closed principle: Changes to the CSS must be made by "extension", creating a new modifier and not changing current styles directly or by changing them under a certain context (being a child of another element)
DRY ("don’t repeat yourself"): It is directly related to the above principles, the CSS classes must be generic so that they can have specific characteristics through the modifiers, ie there should be no two classes that do almost the same thing, instead, creates a class with the general and two modifiers with the specifics
Composition instead of inheritance: New CSS implementations are formed by combining existing ones, this keeps code uncoupled and flexible, for example, if you already have the blocks .button
, .menu
and .popup
, for the creation of a drop-down list, a new block is not necessary, just use existing ones and correctly define their behaviors
It is not recommended to use Wrappers for block positioning, instead mixes should be used:
- To position two brother blocks (
header
and content
), relative to each other, one can create a parent block (.card
) and use two child blocks (.card__header
and .card__content
) that will have the positioning styles, in addition to the original blocks that will be mixed with the children blocks (.card__header.header
and .card__content.content
)
<section class="card">
<!-- Header and navigation -->
<header class="header card__header">...</header>
<!-- Content -->
<div class="content card__content">...</div>
</section>
- If the elements to be positioned are already parents and children, one can use an element entity to handle the positioning, replacing an abstract wrapper
<button class="button">
<span class="button__start">
<span class="icon"></span>
</span>
...
</button>
Creation of HTML can be done manually, that is, write all the code in hand, which, in the long run, is bad from the maintenance point of view, since a change in the structure of entities requires changing the HTML at multiple points
But it’s possible to do that automatically, through templates, by changing it, the existing HTML elements will be updated as well, and can be exchanged for another or extended by new ones. The models are written in a declarative form, allowing the main principles of the methodology to be applied:
- Use of the same terms: The models are defined in the terms block, element and modifier, for this there is an abstraction above the DOM tree, the tree well, which is a "simplified DOM", only with entities, for example, the following HTML code:
<header class="header">
<img class="logo">
<form class="search-form">
<input class="input">
<button class="button"></button>
</form>
<ul class="lang-switcher">
<li class="lang-switcher__item">
<a class="lang-switcher__link" href="url">en</a>
</li>
<li class="lang-switcher__item">
<a class="lang-switcher__link" href="url">ru</a>
</li>
</ul>
</header>
Would have the corresponding tree WELL:
header
logo
search-form
input
button
lang-switcher
lang-switcher__item
lang-switcher__link
lang-switcher__item
lang-switcher__link
Code division: The template code is stored in separate block files according to the organization rules of the file structure. You can create templates for an entire block or separately for elements or modifiers
Use of reset levels: It’s the same idea already described before, applied also to templates, can add and remove entities to the structure or render the same entities differently (for example, changing the HTML tag used)
The methodology also applies to Javascript, keeping the focus on entities and organizing the code according to the structure of files already explained, including the levels of redefinition, where it is possible to add, overwrite or inherit the entities. For everything to work properly and the changes in the DOM do not affect the functioning of the blocks, it is important to implement through the library i-bem.js
(there is also the BEM React, a set of tools to implement the methodology in React)
There are some code writing rules as well...
Declarative style:
The behaviour of each block is described separately
The block states are defined declaratively and, when changing, is automatically called the code that defined for this state
The block logic is described as a set of actions and conditions for the execution of these actions, this makes it possible to separate the functionality of the block into individual parts and use the levels of reset
Encapsulation: The implementation of a block is separate from other blocks and each block provides an API to interact with other blocks. The block statement allows you to hide your internal implementation, and since the elements are always an internal implementation of a block, they can be accessed only through the block API
Inheritance: The declarative description of the block’s behavior makes it possible to use the methods of a base block within a derived block and inherit them, so the new block can obtain all the properties and methods of the base block. You can also create inheritance chains, which means that one block inherits from another that in turn inherits from a third block and so on
Interaction between blocks: The methodology BEM values to work with independent blocks, but in practice this is unattainable. Communication between blocks can be through:
Registration for events from other instances of blocks
Signatures for modifier changes
Direct calls to methods from other instances or to static methods from other blocks
Any interaction patterns. For example, Event Channel: all communication takes place through messages that the components publish and listen to using an intermediary
Interaction of a block with its elements: A block usually has additional helpers to work with its elements, which are the internal implementation of a block. Cannot access an element from another block directly, can only be accessed through the API of the block to which this element belongs
I tried to simplify and summarize the parts, there’s more to delve into and also some things I didn’t put here like build and common problems, as well as the various tools (technologies, Toolbox and libraries)
Now answering the questions on the body...
No, according to your story, exists since 2005, but from its beginnings until today changed everything
- What is the purpose of it?
At first, probably, just standardize how the CSS code is written, today, is a methodology that has several standards and rules to create an organized code, reusable and easy to maintain
It solves certain problems when working as a team, such as one component overwriting another and disorganization of both code and structure. Also, as I said, the methodology focuses on the development of reusable and maintenance-friendly components.
On the other hand, it brings a lot of complexity and some limitations, such as using classes (.checked
) modifiers instead of pseudo-classes (:checked
), what would be more practical, and not reuse of modifiers (for example, .bolder
for bold) between elements and blocks, but there are alternatives
The methodology NAY standardizes class nomenclature, as described above, it has 5 standards of its own and still allows developers to create their own standards. So anyway, developers will have to organize to decide how classes should be named
All links in the reply were removed from documentation
CSS is evil, always :D
– Maniero
Possible duplicate of Good practices using CSS. One of the answers is about GOOD
– Costamilam
It’s another one of those things they created to solve the problem of anyone who mixes a lot of junk, which could be done in a simple way, but that people with little knowledge think they already have enough understanding about CSS (but they don’t even know what Rules are) and they don’t even know how much things could be simplified and get the same result, so they have to invent things to solve difficulties created by their own people because they want to use a series of cacarecos and try to (just really try) avoid getting bogged down.
– Guilherme Nascimento
I voted +1 (and maybe vote to keep it open, I’ll wait for the community) because the question 'seems to me' that could have a focus just on the subject... and I can’t see far the
BEM
as something useful, actually personally I think that the need toBEM
and simplify would be a real "good practice", a question focused on the use ofBEM
, but not to mention that he’s wonderful, just talk when it’s useful, like these fucked-up projects (don’t get me wrong). So I think this place/question is the place to talk about it, maybe I even dare to answer.– Guilherme Nascimento
An addendum to my other comment, I’ve come across work from others of a page (a promotional "landingpage") very simple, with BEM, with FLEX, with GRID, which in the end was a little bigger than expected. Yeah, the so-called "good practice" generated by people who forgot to learn the basics, but manage to use a new thing to do about 10 different things, which usually would not even be necessary or appropriate, should follow the philosophy: "do good without looking at whom" :p
– Guilherme Nascimento