BEM stands for “Block”, “Element”, “Modifier”. It is a front-end methodology: a new way of thinking when developing Web interfaces. This article will elaborate on the theory as well as the practice of building websites at Yandex—one of the leading internet companies in Russia.
Due to the length of this article, it was split into three parts:
When a project is:
If the development team:
Then being able to navigate the code base quickly is crucial.
Block code is easiest to find when it’s placed in files using the same naming scheme as the one we use for naming our entities:
menu.xsl menu.js menu.css
There could be a task:
We want the procedure of block reuse to be as simple as possible—like simply copying the files, or using partial checkout of a repository from a “donor” project. In both cases, it is useful to have all of the files under the same directory:
menu/ menu.xsl menu.js menu.css
When working on a project we might need to change a block at some point.
A manager could ask:
Current Menu Item, orMenu react on hover.A developer could ask their colleague:
Search Form styling for IE.To understand where the relevant code is located, follow these (or similar) rules:
Example
File structure of a Menu block:
menu/
__item/
_state/
menu__item_state_current.css
menu__item_state_current.xsl
menu__item.css
menu__item.xsl
menu.css
menu.js
menu.xsl
Maintaining such file structure manually is, quite obviously, inconvenient. So we’ve developed BEM Tools to handle the burden. These tools help with creating the directory structure, placing files, generating placeholder content, etc.
Big internet portals often need to reuse the same blocks across different websites.
There could be a task:
Footer on all the portals’ websites, orWorking for a Web design agency often means that one has to use typical solutions for typical Web pages.
A project manager could ask you:
We have to do these tasks while preferably avoiding copying blocks around manually. So it’s nice to have a repository of shared blocks that can be linked to a project. Blocks should then be united under a single directory for that.
Such a directory is usually called Blocks.
E.g.
blocks/ foot/ head/ menu/ page/ search/
That directory can be linked to another project straight from the version control system, so that we can make changes to shared blocks in a single location.
If a group of blocks (united under one directory) is linked to a project directly (via a partial checkout, svn:externals, etc.), then every change committed to these blocks influences all projects.
When developing a website based on an existing one, we might want:
Head on site A without affecting site B.To do so, we need to be able to define or redefine blocks in different technologies for a specific website only, or for certain pages only. This can be achieved using Definition Levels.
A Definition Level is a set of blocks grouped in one directory.
An implementation of every block from the library can be changed (or completely redefined) at project level.
From page-building process’ perspective:
build-page -l blocks-common -l blocks-my my-page.htmlFrom the file structure point of view:
On the JavaScript side:
/* blocks-common/dropdown/dropdown.js */
Block('dropdown', {
init: function() {
...
}
});
/* blocks-my/dropdown/dropdown.js */
Block('dropdown', {
init: function() {
this.__base();
...
}
});
From the viewpoint of a template engine:
<xsl:template match="b:head">
<div> <!-- Node for extra design -->
<xsl:apply-imports/>
</div>
</xsl:template>
From the architectural point of view:
Open source block library bem-bl (in development) is an example of having several definition levels in one repository.
Working in terms of blocks means having a Subject-Matter Abstraction. This abstraction is for developers only, and browsers will get a compiled version of the code.
So we have Code For People and Code For Browsers—they are not the same.
To turn Code For People into Code For Browsers we Build a page.
Building A Page means generating HTML, CSS, and JavaScript code from a page declaration (written in XML or JSON) by applying implementations of declared blocks.
On the CSS side:
From the JavaScript point of view:
From the template engine’s point of view:
From the viewpoint of development process:
In terms of work organization:
We use BEM tools to build pages.
The usage of bem tools requires to run several commands for each page whenever page input data or blocks implementation are changed. As a result of these commands, you get CSS and JavaScript files for the page, page’s template, and if you are developing static pages, the HTML code of your page.
To avoid running these commands manually, there is also the GNUmakefile, which was written for a project that includes the instructions on how to build pages.
You can find an example of such a file in the test project bem-bl-test.
But the usage of GNU Make has a list of problems:
So we’d like to create something to replace GNU Make for the process of page building. This will be both a development server and a tool to build production files. Bem Server will be run in a project root directory, and give HTTP response with the page files built (so you won’t need to run gmake manually after each change).
Besides, it will be able to watch the files (the adding and removing of them) via fs.FSWatcher that help to chache results efficiently.
BEM Server is a subcommand of bem-tools. Currently it can run an HTTP server, apply BEMhtml templates to BEMjson data and inline CSS imports using borschik utility.
Yandex is a large (mostly Russian) company that use BEM methodology to develop its services.
BEM methodology does not request that you use a certain framework. You also don’t have to use BEM for all the technologies you have on your pages (but that would be the most efficient).
All the services of Yandex have BEM in their CSS, JavaScript code or XSL templates for their pages. E.g.,
Some services don’t use XSL templates, building their pages with our newest template product, Bemhtml template engine which was mentioned above. These are the following services:
There are also other companies that use BEM methodology.
For example, the guys at Mail.ru partly use BEM for their services. Some blocks on their pages are BEM-based in terms of CSS code. They also have their own C++ template engine, and write block templates according to this methodology.
More examples:
You also may be interested in websites that use bem-bl block library (in development):
Due to the length of the article, it was split into three parts:
(jvb)
I am a front-end developer working for Yandex since 2008. Now being a team-leader of development an UI framework (CSS/HTML/JavaScript + templates) for building Yandex-style sites, I'm also pushing some internal front-end technical solutions into Open Source.
I am interested but skeptical. Javascript templating is great but this seems like unnecessary encapsulation for the sake of creating block objects. For example, on Yandex Maps I was just scanning the source and found this link:
a class=”b-link b-link_is-bem_yes b-link_type_metro i-bem b-statcounter__item b-statcounter__item_clickable_yes b-statcounter__item_path_metro” …
That is a mouthful for one little link. DRY coding practice might suggest that b-statcounter and b-link should be abstracted further up the cascade.
At the end of the day it comes down to time and cost. How much money does BEM and bem-tools save Yandex annually versus a different templating framework or writing vanilla styles with the same BEM principles?
Your are right that SMACCS uses the similar ideas of “modules”. (We did not steal, BEM is 5 years old). But BEM is something different. It is for all the technologies, not only for CSS. We have BEM-based JavaScript and BEM-based templates. That all enable us to collect all about one interface object in one directory which can be easily copied to a new project (or linked to a project by svn:externals).
Also, please, draw your attention at “levels of defenition” concept which is a great part of BEM. It comes to code naturally when we are speaking about CSS. But we also produces JavaScript framework and server-side templates with which you can easily redefine block’s appearance of behavior using your level. That’s very useful. We have our in-home library of blocks to build our sites. And each project has its own level to redefine those blocks without changing anything in the common library.
I have to say it’s really a promising project. As a back end developer, I really love this idea to modulize the front end. I will take time to go deeper and feedback about this project.
Thanks the great article and your sharing to us :)
I’m not entirely sure wether this methodology is nessecary on all but the biggest of websites. I know virtually nothing about BEM, but I could see the amount of overhead becoming monstrous fairly quick. I wonder if there is a point at which it defeats its actual purpose, i.e. preventing duplication and streamlining development. It would be interesting to say to least to see how the amount of abstraction impacts the development process. Either way, it is nice to see that there is renewed interest in front-end methodologies. I think I will just stick with my own slightly modified version of SMACCS for now, though.
Block implementation is mix of multiple technologies, not a single one. Block styles, images, scripts, templates and documentation – it’s all block technologies and it’s all stored in the directory which represents block in the file system. The same is true for the elements and modificators.
Our point of view is that block is primary and technologies it is implemented by are secondary. That’s why at first we separate blocks in file system and then add all needed technologies step by step.
There is no restriction in the methodology. Only dividing a page into blocks, elements and modifiers. You can use as much from the methodology as you wish (not only a full stack). Toolkit is flexible to support that.
The simplest case is using BEM in CSS when you mentally divide your page into blocks but use one CSS file (as usually):
/* head */
.head { … }
.head .logo { … }
/* foot */
.foot { … }
.foot .copyright { … }
But when including one block into another elements can be affected (by cascade). In this case elements of one block are indiscernible from another’s (if those elements have the same CSS class). Again, you cannot tell apart a block and an element.
With that in mind, we came to a rule that element’s name is including a block which element belongs to.
/* head */
.head { … }
.head__logo { … }
/* foot */
.foot { … }
.foot__copyright { … }
The scheme “block__element” is not strict, its only our internal naming convention. You can use another naming and tune bem-tools in accord with your scheme.
When you have many blocks in those one CSS file, you’ll like to divide it into pieces. So, you can have a CSS file for every block. The final (page’s) CSS file can be build manually or with a utility.
head.css
.head { … }
.head__logo { … }
foot.css
.foot { … }
.foot__copyright { … }
project.css
@import url(head.css);
@import url(foot.css);
If you need a place for pictures, it can be the same where CSS files are:
head.css
head__logo..png
foot.css
foot.png
Then, your project is grownig. There are a lot of blocks. And some new technologies are coming up (javascript, templates, documentation) Since then block directories became handy:
head/
head.css
head__logo..png
head.js
head.md
foot/
foot.css
foot.png
foot.md
Again, you can use as much from the methodology as you wish.
If I understand you correctly, by “this” you mean incapsulation, polymorphism and inheritance. This is what BEM think about that:
Incapsulation happens by design. Every block can be used as a part of another more complex one. Thanks to unique CSS classes and avoding Tag Selectors, you are free to include any block into another.
Polymirphism happens by 2 reasons. First, there are modifiers. They are to slightly change block appearance or behaviour. Besides, there are definition levels which enable you to use a set of block from a common library (first level) and slightly redefine them at your project (second level).
Inheritance is possible via polymorphism. You can have something basic and then some specific cases inheriting. Also there is a “mixin” term in BEM. Two or more blocks and element can be placed at teh same DOM node. Mixins are successfully used in many programming languages as a way to reuse basic code.
Great article!
It’s a great deed to abstract components from the whole (webpage). I would like to get a deeper insight into this. The reason is that I had similar thoughts about bringing Component Object Model/OOD into the web with all the consequent meanings of that – like incapsulation, polymorphism (well, inheritance – suppose if I want to take a button, and inherit from it by adding another properties like borders or colors etc..). My bet that this paradigm is better suited for the big websites, but on another perspective – reusability is also great for the smaller dimension fields, e.g. web design companies etc. Does BEM support this? Thanks.
Yay! You've decided to leave a comment. That's fantastic! Please keep in mind that comments are moderated and rel="nofollow" is in use. So, please do not use a spammy keyword or a domain as your name, or it will be deleted. Let's have a personal and meaningful conversation instead. Thanks for dropping by!
Dylan Valade
April 16th, 2012 11:30 amI am interested but skeptical. Javascript templating is great but this seems like unnecessary encapsulation for the sake of creating block objects. For example, on Yandex Maps I was just scanning the source and found this link:
a class=”b-link b-link_is-bem_yes b-link_type_metro i-bem b-statcounter__item b-statcounter__item_clickable_yes b-statcounter__item_path_metro” …
That is a mouthful for one little link. DRY coding practice might suggest that b-statcounter and b-link should be abstracted further up the cascade.
At the end of the day it comes down to time and cost. How much money does BEM and bem-tools save Yandex annually versus a different templating framework or writing vanilla styles with the same BEM principles?
Anthony Madhvani
April 17th, 2012 2:44 amI’m not entirely sure wether this methodology is nessecary on all but the biggest of websites. I know virtually nothing about BEM, but I could see the amount of overhead becoming monstrous fairly quick. I wonder if there is a point at which it defeats its actual purpose, i.e. preventing duplication and streamlining development. It would be interesting to say to least to see how the amount of abstraction impacts the development process. Either way, it is nice to see that there is renewed interest in front-end methodologies. I think I will just stick with my own slightly modified version of SMACCS for now, though.
Varvara Stepanova
April 17th, 2012 5:40 amYour are right that SMACCS uses the similar ideas of “modules”. (We did not steal, BEM is 5 years old). But BEM is something different. It is for all the technologies, not only for CSS. We have BEM-based JavaScript and BEM-based templates. That all enable us to collect all about one interface object in one directory which can be easily copied to a new project (or linked to a project by svn:externals).
Also, please, draw your attention at “levels of defenition” concept which is a great part of BEM. It comes to code naturally when we are speaking about CSS. But we also produces JavaScript framework and server-side templates with which you can easily redefine block’s appearance of behavior using your level. That’s very useful. We have our in-home library of blocks to build our sites. And each project has its own level to redefine those blocks without changing anything in the common library.
Nick Gassmann
April 17th, 2012 11:55 amI was right there with you until you started modularizing the files and folder structure. That just looks like a major headache. What’s wrong with simply commenting your code and breaking it up there?
Roman Komarov
April 18th, 2012 3:37 amSee that comment by Leonid — http://coding.smashingmagazine.com/2012/04/16/a-new-front-end-methodology-bem/#comment-577253
The BEM in file system is great for big projects or frameworks. And the modules are great for code reuse — even for small projects it’s easier just to copy reset.css, typography.css, grid.css etc. from the previous project, then trying to find all the needed styles in the one big stylesheet.
Vitaly Harisov
April 18th, 2012 4:05 amBlock implementation is mix of multiple technologies, not a single one. Block styles, images, scripts, templates and documentation – it’s all block technologies and it’s all stored in the directory which represents block in the file system. The same is true for the elements and modificators.
Our point of view is that block is primary and technologies it is implemented by are secondary. That’s why at first we separate blocks in file system and then add all needed technologies step by step.
Vitaly Harisov
April 18th, 2012 4:06 amModularizing is to build different sites from the same blocks. If you go to some Yandex sites, you’ll see that they have some similar interface objects (blocks). They are slightly different (mostly in appearance) but have a lot of in common.
Yandex is a portal of 150 sites and that’s wrong and expensive to copy&paste pieces of code about all interface objects which are the same. Especially if your CSS code is in one place, JavaScript is in another and so on. Again, there should be a possibility to change those objects at all the projects.
So, having all (CSS, JavaScript, templates, documentation) about one block in its folder enable us to link this block to a new project. That is by linking a folder via svn:externals, by copy & paste block’s folder automatically (with tools) or manually.
Since blocks on different sites are similar but not the same, we should redefine them a bit. So, the is a concept of levels. We have our internal library of more than 100 blocks which are one level. And every project can have its own level to slightly change blocks. That works for all the techs: CSS, JavaScript, templates.
Having a reusable code library is also useful for web-design agencies to save their time.
Val Kotlarov Hoffman
April 17th, 2012 10:36 pmGreat article!
It’s a great deed to abstract components from the whole (webpage). I would like to get a deeper insight into this. The reason is that I had similar thoughts about bringing Component Object Model/OOD into the web with all the consequent meanings of that – like incapsulation, polymorphism (well, inheritance – suppose if I want to take a button, and inherit from it by adding another properties like borders or colors etc..). My bet that this paradigm is better suited for the big websites, but on another perspective – reusability is also great for the smaller dimension fields, e.g. web design companies etc. Does BEM support this? Thanks.
Sergey Berezhnoy
April 18th, 2012 8:20 amIf I understand you correctly, by “this” you mean incapsulation, polymorphism and inheritance. This is what BEM think about that:
Incapsulation happens by design. Every block can be used as a part of another more complex one. Thanks to unique CSS classes and avoding Tag Selectors, you are free to include any block into another.
Polymirphism happens by 2 reasons. First, there are modifiers. They are to slightly change block appearance or behaviour. Besides, there are definition levels which enable you to use a set of block from a common library (first level) and slightly redefine them at your project (second level).
Inheritance is possible via polymorphism. You can have something basic and then some specific cases inheriting. Also there is a “mixin” term in BEM. Two or more blocks and element can be placed at teh same DOM node. Mixins are successfully used in many programming languages as a way to reuse basic code.
David Trindade
April 18th, 2012 4:27 amI was kind of liking it until about halfway the second part – by the end it had completely alienated me.
(I’m only into the HTML/CSS and Jquery side of front-end dev)
In my view it’s too much abstraction and too many different technologies to make it work – and I can only see something like this working alright in massive portals.
The other 95-99% of projects out there would probably suffer from all the hassle having to set all the files, dependencies and modules to make it work.
Not for me at all.
Vitaly Harisov
April 20th, 2012 4:40 amThere is no restriction in the methodology. Only dividing a page into blocks, elements and modifiers. You can use as much from the methodology as you wish (not only a full stack). Toolkit is flexible to support that.
The simplest case is using BEM in CSS when you mentally divide your page into blocks but use one CSS file (as usually):
/* head */
.head { … }
.head .logo { … }
/* foot */
.foot { … }
.foot .copyright { … }
But when including one block into another elements can be affected (by cascade). In this case elements of one block are indiscernible from another’s (if those elements have the same CSS class). Again, you cannot tell apart a block and an element.
With that in mind, we came to a rule that element’s name is including a block which element belongs to.
/* head */
.head { … }
.head__logo { … }
/* foot */
.foot { … }
.foot__copyright { … }
The scheme “block__element” is not strict, its only our internal naming convention. You can use another naming and tune bem-tools in accord with your scheme.
When you have many blocks in those one CSS file, you’ll like to divide it into pieces. So, you can have a CSS file for every block. The final (page’s) CSS file can be build manually or with a utility.
head.css
.head { … }
.head__logo { … }
foot.css
.foot { … }
.foot__copyright { … }
project.css
@import url(head.css);
@import url(foot.css);
If you need a place for pictures, it can be the same where CSS files are:
head.css
head__logo..png
foot.css
foot.png
Then, your project is grownig. There are a lot of blocks. And some new technologies are coming up (javascript, templates, documentation) Since then block directories became handy:
head/
head.css
head__logo..png
head.js
head.md
foot/
foot.css
foot.png
foot.md
Again, you can use as much from the methodology as you wish.
RGBboy
April 21st, 2012 5:49 pmWow! Thank you so much for sharing these concepts. I have been thinking a lot lately how html, css and js are still very intrinsically coupled, especially when you need to cater for older browsers (I’m lookin at you IE). For example, you can code html to a high semantic level, but when it comes to achieving a certain look, you are forced to add html elements to get there.
I really like your ideas of concentrating on what you are setting out to achieve first, then breaking it into the smallest divisable pieces (your blocks) then combining the tchnologies you need to achieve it.
I can see that many people will soon begin creating ther own bem libraries to share with the world. It’s great!
I do have a couple of questions though. How do you incorporate a content management system into this concept? How does dynamic content get injected into the BEM templates?
Alex Yaroshevich
September 16th, 2012 9:14 amAs far as I know if your CMS can produce text output (like HTML or something) — you just need to divide all of your data and all your view. There is no place to template engines like Smarty, Twig, etc. because their template files contains both: html and data output. BEM methodoly works like a charm but needs data divided from view. The best examples here are xml for data + and xslt for representing data in html, bemjson (data) + bemhtml (for html). But web here is just a little part of all possibilities.
For example you have a simple page with 2 blocks encapsulated to 1 page block. These 3 blocks have 3 different views. Page block is static but 2 other blocks are generating for users differently. And when your system getting request to show some page you deciding which blocks need to show. All needed blocks must be included to resulting page structure: page { block1, block2 }, page { block2 { block1 } }, or any other version.
In other words any CMS can easily produce pure blocks of data in some specific format. And then all of that blocks just combining one to another… to big structure of concrete page. Resulting structure contains all data needed to draw page to html and you just need to put the whole page to render page view. Anywhere. Even in console or mobile device if you have render for that.
Just now you operating with blocks. Nothing more. It’s simple and beautiful.
roberto
October 12th, 2012 12:17 pmI’m really digging this whole BEM methodology. I accidentally discovered it while moving away from bootstrap (which is really just a style guide) and trying to architect a larger site on my own. There is one addition I’m gonna make in my own projects though: I will separate “Page Level Blocks” from “Element Wrapper Blocks”. I’ve been reading into SMACSS as well, and there he has a “Layouts/” folder. I think it makes sense to put page level blocks there. Then in my BEM “blocks/” folder, I’ll put the element level blocks.
Also, for the element level blocks, I kinda feel like these should almost always be DIVs. You can certainly attach classes to forms, ul, p, etc…but I feel like the block is the container/division and that’s usually a div. However this leads to the dilemma of having too many divs! Another thought that just came to me is that forms and uls are really containers so I could probably see them as element level blocks rather than elements themselves…but then again according to html5, these should most likely be wrapped in a *section* element, so the section or div is really the block(?). A little confusing, but would really like to hear your response. Thank you for a wonderful system.
nXqd
April 24th, 2012 6:50 amI have to say it’s really a promising project. As a back end developer, I really love this idea to modulize the front end. I will take time to go deeper and feedback about this project.
Thanks the great article and your sharing to us :)