These principles are based on the combined experience of our team. We took all the best approaches from the past, in order to avoid repeating previous mistakes when developing new libraries. We encourage the community to follow these guidelines when using and developing BEM libraries.
The libraries are developed on GitHub, where all the tasks, plans, and deadlines are available. Any developer can participate in working on a library: create a task with requests for the team, or send a pull request.
The library must be as simple as possible. Give up anything that could be understood or used in more than one way.
When designing needed functionality, strive for intersecting needs, rather than combined features. When you have to make a choice, prefer the option that solves the problem with less code and fewer BEM entities, or the one that will be easier to support.
The library code must be 100% covered by tests. This guarantees fewer errors and saves time on support in the future. Code is not considered finished and stable until it is covered by tests. Pull requests are not accepted if they do not add or change tests.
All the names for fields and methods should be standardized with one or more compatible libraries. If the methods, modifiers, or fields in a block are named in a certain way, the same naming logic must be used in a similar task. The consistency and coherency of all entities must be perfected and brought to the forefront. The naming logic must be clear to other developers who will be using the library or modifying its code.
A block private API shouldn't be used outside of this block.
During development, plan ahead to make fine tuning possible on the user side.
The library must support multiple themes. This makes it possible to create formatting rules for each style, as well as avoid conflicts with new themes. The main theme of the BEM libraries right now is the ”islands“ theme, which implements the new design for Yandex services. The implementation of multiple themes within a single library is demonstrated in bem-components, where the ”islands“ theme is supplemented with the ”simple“ theme.
A method name must reflect the method purpose as exactly as possible and make it immediately clear what it implements. This approach can shorten the learning curve and make the API more intuitive.
Explicit is better than implicit, but in some cases, shortcuts can be used in the API. Custom BEMJSON chunks may be passed only where this is truly necessary — for example, if the entity is semantically a wrapper or container. For complex blocks where content generation is the internal API, you need to create shortcuts, omitting the ”content“ field. This reduces the volume of the BEMJSON input and makes it painless to change the internal structure of complex blocks.
Defaults must be declared explicitly, as this is an external API. Any changes to defaults interfere with backward compatibility. Defaults that are implicit and not documented anywhere create problems for supporting the library.
Check input data before using it. In case of an error, generate an exception that can be handled in the code being called. Error handling must be consistent across the entire library. Do not add complicated data validation to a block if it doesn't occur in a similar situation.
Everything that can be expressed using a BEM entity must be expressed through one.
Do not create a BEM event or subscribe to one if it is possible to work with an event for changes to modifiers.
A modifier is a predefined set of conditions or states. A special field is a set of variable values that are not known in advance. Everything that can be expressed as a finalized set of values should be implemented as a modifier. When this is not possible, use special fields.
Use object oriented programming only where it is justified. In all other cases, use mixes, delegation, and composition.
The interaction between blocks should be built from the bottom up. A block can only interact with mixed and nested blocks, not with external or nearby blocks.
Optimization decisions must be implemented during the development of each specific block. Think through the possible ways to optimize in advance, so that later it is easier to use them in code that has already been written.
Automate all repeated processes, such as inserting images, arranging prefixes, or copying styles. The developer shouldn't spend time on routines when there are robots to do that.
The library must support mobile platforms. We do not recommend using an adaptive layout. The library must work on all browsers that you declare supported: the only degradation allowed is in the styling of components, but not in functionality. Code at the ”common“ and ”desktop“ levels must work on touch devices. For an example, review the list of supported browsers for the bem-components library.
The library components must be accessible for screen reader programs, but you shouldn't expand the public API for this purpose. All the required ARIA attributes are set using templates and scripts.
The library is in development with a focus on the future. Always use the latest versions of browsers and tools, to keep the library relevant for development as long as possible.