Skip to content

Latest commit

 

History

History
1367 lines (1051 loc) · 42.2 KB

yandex-frontend-dev.en.md

File metadata and controls

1367 lines (1051 loc) · 42.2 KB

What you can borrow from Yandex front-end dev

The article is a text version of a presentation given at Riga WebConf in November 2012.

The article sums up Yandex over 7-year experience in finding solutions for efficient front-end development.
Yandex, as a search engine and the larges Internet company in Russia, enjoys the major share of the local market and provides over a hundred of associated services with the help of 2500 developers and 150 front-end engineers among them.

Yandex developers jointly produce solutions for the problems they run into. At the same time, Yandexoids are truly nerds connected to the world outside Yandex via conferences, hackatons and meetups. So, the solutions produced by Yandex developers perfectly work outside and can be easily shared.
Here is a piece of such sharing.

Web interface

Look at the draft for an online shop. As you can see, it's nothing special. Just an ordinary web site providing all the generally accepted possibilities, such as navigation through the site pages, searching books, some advertising parts and so on.

As web developers, you know that behind the page there are our dear HTML and CSS.

    <!DOCTYPE html>
    <html>
        <head>...</head>
        <body>
            ...
        </body>

    body {
        font: 0.8em Arial, sans-serif;
        margin: 0;
        color: black;
    }
    .sidebar ul li {

Also, besides the page is really combination of HTML and CSS, it's also a set of interface pieces.

Each piece is to do something. It provides to a user a functional or design point.

Each has its purpose, similar to pieces of furniture…
A chair is to sit on, a cupboard it to keep the kitchen things. A bed is to lay on, and a coffee machine helps to survive through deadlines.
You can use furniture to fill our rooms.

Also, you can use interface components to fill pages.

Pages are built with this pieces like houses are build with blocks. So, let's call them just that, blocks.

Block

A block is an independent interface piece that preserves a design point and some functionality. Anything that can be taken as a solid piece and can be put into a page is an interface block.

To operate the blocks, it's good to name them. Here there are a Menu, a Calendar control, a Footer, a Tabbed pane, a Dropdown and a Search blocks.

Futhermore, some blocks are large. They usually preserve other blocks. But they still are solid independent pieces.

Here you can see the Header block that contains some others.

Block HTML representation

Indeed, behind the scenes there are our dear HTML and CSS.

Each block is represented by a piece of HTML markup. To style the block you can write the CSS rules, as usual.
Menu block is an ul tag and its content.

    <ul class="menu">
        <li><a href="/new">New titiles</a></li>
        <li><a href="/soon">Coming soon</a></li>
        <li><a href="/best">Bestsellers</a></li>
        ...

The same works for the Search block, that is represented by div tag with some content.

    <div class="search">
        <input type="text" name="search" value="..."/>
        <input type="button" name="sbmt" value="Search"/>
    </div>

The last example is the Tabbed Pane block, which is also a combination of HTML and CSS.

    <div class="tabbed-pane">
        <ul>
            <li>Bestsellers</li><li>...</li>
        </ul>
        <div>
           The Casual Vacancy, J.K. Rowling
        </div>
     </div>

Independent CSS blocks

But in order to build pages with blocks, we developers should be sure that these interface pieces can be put into any place on a page. This can be possible only if blocks are independent.

Block independency means the following.

A block must not be affected by its ancestors, and in its turn must not affect the descendants.
Regardless of where this block is placed.

When filling a page with blocks, we developers, shouldn't care where exactly each block is placed. You just define a set of blocks with the appropriate order. And that's enough for getting a complete functional page.

    <html>
        <head>..</head>
        <body>

            <div class="head">
                <div class="logo">...</div>
                <ul class="menu">...</ul>
                <div class="search">...</div>
            </div>

            <div class="layout">...</div>

            <div class="foot">...</div>

        </body>
    </html>

But, of course, this maybe possible only due to some architectural requirements to each block. Let us now see what these requirements are. For this let's have a look at what situations can cause block affection and how to prevent them beforehand.

Repeating

The first is repeating blocks.

The same block can appear on the page. For example, one more Menu block can be placed into the Foot block.

Since now the Menu block is not a unique within a page. Because of that you cannot use id selectors to match the CSS rules to it, this would be invalid.

So,

To apply CSS to a block, you should use classname selectors.

wrong

    <ul id="menu">
        ...

    #menu {
        ...

right

    <ul class="menu">
        ...

    .menu {
    ...

This rule is correct for any block.
Even if you think now that the block is unique within a page, this can be changed in the future. So, the best practice is to avoid id selectors at all and use classes.

Moving within a page

The next that can happen with a block is its movement within a page.

<iframe width="560" height="315" src="https://www.youtube.com/embed/suLQEIcc68g" frameborder="0" allowfullscreen></iframe>

As you can see in the video, the Tabbed Pane block was moved to he right side of the page and immediately got broken since it has new ancestors, new parent DOM nodes now.
This is that must not happen. You should guarantee that a block will work correctly in any place on the page.

Actually you can ensure this only by avoiding cascade in CSS.

Such a recomendation sounds provocative. But anyway this is reasonable. Now let's see why.

Cascade is a kind of relations between objects. A cascade rule says that one object depends on another. It is a connection that can give some benefits.
But you should have a control over all those connections. If not, this may break all.

Trying to fix, developers usually add even more connections into the system. That seems to work at first. But each addition just increase uncontrolable mess.

The more cascade code you bring into the service, the more is the risk of future damages.
So, you should use cascade only when it's really necessary.

I'll show below the situation when cascade is possible. But in general the suggestion is to avoid it.

Moving within a site

The next block adventure is to be moved from page to page.

The already familiar Tabbed pane block can be widely adopted. We can use it on many pages. Of course, on a different page it has another parent block. As I've said above, you should guarantee that it works correctly regardless of its environment. This is what you achieve due to avoiding cascade.

Again, even if a block now is a single one within a whole site, that does not mean it should depend on its surroundings.
The recommendation about avoiding cascade works for all the blocks.

Pages are sets of blocks

The other point is that when you are developing and maintaining, the block set of every page changes.

We, developers, should think about keeping associated CSS in the actual state. So that if a block was removed from a page, we should remove its CSS code. Also, if a block was added to a page, we should ensure its CSS is linked there.
That is not a problem for sites of 2-3 pages since we can keep all the stuff in a single one CSS file.
But usually life is not that easy; there are several pages that are different but still have some common design solutions. At least the Header block is included in all the pages.
So, developers usually place the common stuff into the common.css file. Everything else is distributed per pages.

But let us look a bit closer to this practice.

As you see in the picture, the Header block contains the Search block. This design solution seems to be invariable within the whole site.

But not. The page providing advanced search form doesn't have this Search block in the Header.

So, should we include the Search block code into common.css file? Seems like shouldn't. Well, should we copy-paste it for all the other pages? Again, no.

Moreover, this is just a simple example. In the real life the variety of interface object combinations indeed can be huge. Usually it is very hard to define the common stuff.
On the other hand, copy paste is even worse.

So, there should be a way out.

What about turning these drawn sets of blocks into code?

You can store CSS code for every block separately, each in a file with a corresponding name.

blocks/
    header.css
    menu.css
    button.css
    tabbed-pane.css
    logo.css
    footer.css

So that, CSS for the Menu block is in the menu.css file, CSS for Tabbed Pane block is the tabbed-pane.css file and so on.

Then, you can pack the CSS files for the pages with these blocks using an import keyword.

    @import url(blocks/header.css);
    @import url(blocks/menu.css);
    @import url(blocks/tabbed-pane.css);
    @import url(blocks/text.css);
    @import url(blocks/logo.css);
    @importurl(blocks/footer.css);

That enables you to take only what's necessary for a page.

As a result there is a block stack of our project, stored in a special folder. And some pages that use these blocks.

Looks cool, but

Inside a block

So, let's have a look what is inside our blocks.

The Menu block is going to be the first example.

    <ul class="menu">
        <li><a href="/new">New titles</a></li>
        <li><a href="/soon">Coming soon</a></li>
        <li><a href="/best">Bestsellers</a></li>
        ...
    </ul>

It's represented by ul tag and has some li children for the items. Also, the ul tag is marked with a CSS class, so that you can apply the rules to it.
But the question is "What to do with the items?"

The wide-spreaded solution is to write the CSS selector similar to the following.

    .menu li
    {
        list-style: none;
        display: inline-block;
        padding: 0 0.5em;
    }

As you can see, cascade is used here. It seems to work right at first, because all the reasons I listed against cascade are not for this situation. li tags are always inside their ul parent. So, nothing bad should happen.

But even inside such a small interface piece like a menu item there can be a lot of HTML markup in the future.

Here you can see that a Dropdown block with its own list was placed into the menu item and immediately got broken because of this CSS instruction affects it.
We got the long menu sausage instead of a nice dropdown.

As you can see, except of avoiding cascade there appears even more specific rule.

You should not use tag selectors.

The additional explanation why it is a bad practice to use tag selectors can be easily found in the Internet.

The style system matches rules by starting with the key selector, then moving to the left (looking for any ancestors in the rule’s selector).

Further information can be found in Davis Hyatt's article, from Mozilla.

However we still need a solution to style menu items inside the Menu block.

Element

First, let's clarify a definition and call the things inside a block — elements.

This is a clear picture of what elements are.
As you can see, elements are non-independent pieces of an interface. They make no sense on their own, but are to be used within their parent block.

For example, the Search block has an input element and a button element.

The Tabbed Pane block has 2 tab elements (and can have more if necessary) and the pane element to keep its content.

Styling elements you should think about them as self-reliant entities.

To apply CSS rules to the elements you will need to mark them with classes.
In turn, to avoid cascade, it's necessary to prefix these classes with the block name.

    <ul class="menu">
        <li class="menu__item"><a href="/">Index</a></li>
        <li class="menu__item"><a href="/new">New</a></li>
        <li class="menu__item"><a href="/offer">Special offer</a></li>
        <li class="menu__item"><a href="/shipping">Shipping</a></li>
    </ul>
    .menu__item
    {
        list-style: none;
        display: inline-block;
        padding: 0 0.5em;
    }

You can see here that CSS class for a menu item consists of block name, which is menu, element name, which is item and a group of separation symbols.

We, at Yandex, use 2 underscores for separation. But that's optional. You can choose another symbol or a group of symbols.

    .block__element
    .block-element
    .block--element

If you don't like 2 underscores, maybe you'll be pleased with 3 ;-)

Optional elements

So far so good, a block can be different from page to page.

The difference you can see in the slide is that it comprises different sets of elements. So that, elements are optional. This means you should be able to take CSS code for the elements we use.

Similar to blocks, elements can be stored separately.

    blocks/

        search.css
        search__checkbox.css
        search__autocomplete.css

        tabbed-pane.css
        tabbed-pane__tab.css
        tabbed-pane__pane.css

        menu.css
        menu__item.css

        book.css
        book__title.css
        book__image.css

That enables you to take element code only if you want. If not, you just won't write the import instruction linking it to your page.

Modifier

Now to the last notion, a modifier.

Again, the same block sometimes can look slightly different. Here it is not because of optional elements but because of its own design distinctions.

Of course, it is always possible to implement all these tabbed panes as diverse blocks. But that would be copy paste which we we can't abide.

The way out is to equip a block with an additional CSS class to provide changes. Such an addition is called a modifier.

    <div class="tabbed-pane tabbed-pane_theme_blue">
        <ul>
            <li class="tabbed-pane__tab">Tab 1</li>
            <li class="tabbed-pane__tab">Tab 2</li>
        </ul>
        <div class="tabbed-pane__pane">
            ...
        </div>
    </div>

Remember, we were wise enough to use classes. So, we can add to a block DOM node as many modifiers as we need.

    <div class="tabbed-pane
                tabbed-pane_theme_blue
                tabbed-pane_direction_bottom">
        ...
    </div>

    <input class="button
                  button_theme_black
                  button_size_l" ... />

You can use different modifiers to change different properties. For example, the theme modifier can change block background color and the size modifier fixes all the dimensions of the block.

block-name_mod-name_mod-val

A modifier is a key-value combination, it consists of modifier name, modifier value and is prefixed with block name.

    tabbed-pane_theme_blue
    tabbed-pane_theme_white

    tabbed-pane_size_s
    tabbed-pane_size_l

    button_size_s
    button_size_l

Indeed, modifiers are optional. You almost never will need to link to a page all the block modifiers since blocks are rarely used in all their modifications within one page.
So, similar to optional elements, you can detach their CSS code into their own files.

    blocks/
        tabbed-pane.css
        tabbed-pane__tab.css
        tabbed-pane__pane.css
        tabbed-pane_theme_blue.css
        tabbed-pane_theme_black.css
        tabbed-pane_direction_bottom.css

When building a page CSS file of blocks, you can take only those modifiers which it needs.

Modifying elements

Elements can be modified in the same way.

The famous examples of modified elements are active tabs and menu items. They look a bit different from their friends.

To deliver design changes to an active tab, you need to add a modifier to an element. Similar to what we was doing for blocks.

    <div class="tabbed-pane">
        <span class="
            tabbed-pane__tab
            tabbed-pane__tab_state_current">...</span>
    </div>

Block modifier does affect element

Now I'm going to show you where cascade is possible.

You can see a modified block here. It has a blue theme. Of course, when having a blue theme the block should guarantee that its elements will work correctly. In this situation you allow the block affect its elements.

    .tabbed-pane_theme_blue
    .tabbed-pane__tab
    {
       background-color: #9CF;
    }

Here cascade is possible because the tabs appearance DOES depend on block modifier.


And just to wrap up, to make your blocks independent, be sure that

  • a block has its "name"
    • no "id" but "classname" selectors
  • avoid cascade
  • no "tag" selectors

Block file structure

All the previously shown examples used flat variant when CSS files for blocks, elements and modifiers are placed into one folder blocks.

    blocks/

        tabbed-pane.css
        tabbed-pane__tab.css
        tabbed-pane__pane.css
        tabbed-pane_theme_blue.css
        tabbed-pane_theme_black.css
        tabbed-pane_size_l.css
        tabbed-pane_size_s.css

        menu.css
        menu__item.css
        menu_size_l.css
        menu_size_s.css

        logo.css

        search.css
        search__checkbox.css
        search__autocomplete.css

That works for not very large projects and not very complicated blocks.

If you expect many blocks with elements and modifiers, it's good to contain all the files related to a block in a block folder.

    blocks/

        tabbed-pane/
            tabbed-pane.css
            tabbed-pane__tab.css
            tabbed-pane__pane.css
            tabbed-pane_theme_blue.css
            tabbed-pane_theme_black.css
            tabbed-pane_size_l.css
            tabbed-pane_size_s.css

        logo/
            logo.css

        menu/
            menu.css
            menu__item.css
            menu_size_l.css
            menu_size_s.css

        search/
            search.css
            search__checkbox.css
            search__autocomplete.css

Less mess, and also it's much easier to copy block files from project to project.

We, at Yandex, use the most detailed structure with internal folders for elements and modifiers.

    blocks/

        tabbed-pane/
            __tab/
                _state/
                    tabbed-pane__tab_state_current.css
                tabbed-pane__tab.css
            __pane/
                tabbed-pane__pane.css
            _theme/
                tabbed-pane_theme_blue.css
                tabbed-pane_theme_black.css
            tabbed-pane.css

It is not obligatory, but just works for our case.

Now, before proceeding to the next section, let us sum up.

  • First, any interface is a set of blocks, which can be combined in different ways, can be placed one into another, can change their parent block. And nothing bad should happen since the blocks are independent.
  • Also, all the nested tags in a block are elements.
  • And finally, both blocks and elements can be modified.

BEM

Now, that the three terms are introduced, I am happy to present you BEM methodology. You've just learnt its parts related to independent CSS blocks.

Furthermore, BEM brings some other interesting solutions.

  • First, BEM is a methodology. It's a way of thinking when developing. It provides us with data domain applicable for all the technologies.
  • Besides, BEM is a toolkit automating your work.
  • Finally, BEM is a range of reusable code libraries, making you to develop
  • faster and better.

Now let's have a look at all these opportunities in a little more detail.

CSS for IE

First, I'd like to show how we deal with our bosom friend, the IE browser.

It is possible to link an additional CSS file to a page, especially for IE. Using conditional comments you make other browsers ignore this file. So that, there we can write fixes for IE only.

    <html>
        <head>
            <!--[if gt IE 7]><!-->
                <link rel="stylesheet" href="index.css">
            <!--<![endif]-->
            <!--[if lt IE 8]>
                <link rel=stylesheet href="index.ie.css">
            <![endif]-->
        </head>
        ...

Inside the ie.css file you import the general CSS file for the page.

    @import url(index.css);
    @import url(blocks/menu/menu.ie.css);
    @import url(blocks/button/button.ie.css);
    @import url(blocks/footer/footer.ie.css);

Then, you can redefine CSS that doesn't work correctly for every piece of interface. It's logical to do it separately for each block.

Blocks that need special IE hacks are equipped with additional ie.css files. If all the block files are under the block folder, we can just place one more file in it.

    blocks/

        tabbed-pane/
            tabbed-pane.css
            tabbed-pane.ie.css
            ...

        menu/
            menu.css
            menu.ie.css

The same works for elements and modifiers.

    blocks/

        tabbed-pane/
            tabbed-pane.css
            tabbed-pane.ie.css
            tabbed-pane__item.css
            tabbed-pane__item.ie.css
            tabbed-pane_theme_blue.css
            tabbed-pane_theme_blue.ie.css with

So, a block folder encapsulates all the CSS needed. Using the project block stack we can assemble CSS files for pages, both the general one and for IE.

JavaScript

HTML/CSS dummy is not a functional web application yet. But implementing some JavaScript logic we can paint it with colours.

We should code that the Tabbed Pane block reacts on leftclick.

The Dropdown block functionality is that it is hidden when a page is just loaded. But if a user makes clicks with the left mouse button on its switcher, the block shows.

The Dropdown also can be smart enough to calculate its direction according to its place on a page. In the picture the second Dropdown block opens up since it's too close to the bottom.

This needs JavaScript logic which you have to provide for a page. Pages are usually supplied with JavaScript logic by linking a .js file to it.

Sets of block in JavaScript

Again, for small projects all the magic can fit comfortably into a single one JavaScript file.

    <!DOCTYPE html>
    <html>
        <head>
            <link rel=stylesheet href="index.css"/>
            <script type="text/javascript" src="all.js"></script>
        </head>
        ...

But usually we have different functionality for different pages. So that similar to CSS we a have separate JS file for every page.

    <!DOCTYPE html>
    <html>
        <head>
            <link rel=stylesheet href="index.css"/>
            <script type="text/javascript" src="index.js"></script>
        </head>
        ...

Again, block set of a page can be changed and you need to ensure that you link corresponding JavaScript.

Similar to CSS for blocks, you can detach a separate js file for every block and store it under the block folder.

    blocks/
        menu/
            menu.css
            menu.js
        dropdown/
            dropdown.css
            dropdown.js
        tabbed-pane/
            tabbed-pane.css
            tabbed-pane.js

Inside the menu.js file there is a piece of logic related to the Menu. The same for the Tabbed Pane.

Using these pieces of logic you can build JavaScript file for a page similar to what you've done with CSS before.

    borschik:include:blocks/menu/menu.js
    borschik:include:blocks/tabbed-pane/tabbed-pane.js
    ...

Each line in the file refers to a particular block.

CSS and JavaScript flattening with borschik

Don't be confused with an unfamiliar include instruction. Of course, we are not going to supply a browser with such a strange file but flatten each include.

    /* Menu block begins */
    (function($){
        $('.menu__item').on('click', function(e) {
            $(this).toggleClass('menu__item_state_current');
        });
    })(jQuery)

Here you can see here that including line for the menu turned into the content of the file.

You can do such inlining magic automatically with the tool called borschik.

Besides flattening JavaScript, it does the same with CSS files of imports.

You can work with imports when developing, but for production it's better to decrease the amount of CSS files. Each CSS @import causes an HTTP request making a browser to load many files.

    @import url(blocks/header.css);
    @import url(blocks/menu.css);
    ...

Using borschik to prepare a project for production deployment you can turn all the imports into relevant CSS content.

    .header {
        ...
    }
    .menu {
        ...
    }

This is very important that borschik works correctly with relative paths in CSS. So, it's not just stupid inlining.

blocks/menu/menu.css

    .menu {

        background: url(menu__bg.png);

    }

pages/index.css

    @import url(blocks/menu/menu.css);

pages/_index.css

    .menu {

        background: url(../blocks/menu/menu__bg.png);

    }

Building page files

The page which a browser gets is not one piece of code. As you've already seen, it is a bunch of at least 4 files, which are HTML, 2 CSS files and JavaScript.

When the page is under development or is maintained, set of its blocks can change. If a block was included into the set or removed from it, we are to change all the files.
Actually it is a monkey job that definitely can be automated.

The images shows us what are the blocks on the page and which ones contain others.

We got this information with a visual language the picture provides. But the same can be described in text. Any nesting format works for it.

    <b:page>
        <b:head>
            <b:logo/>
            <b:search>
                <e:input/>
                <e:button/>
            </b-search>
            <b:menu>
                <e:item>Home</e:item>
                <e:item>Contacts</e:item>
                ...

In Yandex it used to use XML, but now it’s JSON.

{
        block: 'page',
        content: [
            {
                block: head,
                content: [
                    { block: 'logo' },
                    {
                        block: 'search',
                        ...

This page declaration is called BEM tree by analogy to DOM tree.

The format describes what are the blocks on a page, preserves their nesting structure, elements and modifiers which blocks are using.
Such a format can be parsed with a special tools and turned into the CSS and JavaScript files automatically.

The BEM tree can be turned into all the necessary static files. And if you need changes, you can fix BEM tree, run transformation process again and get updated files.

These transformations are possible with a toolkit called BEM tools. It's open sourced and hosted on GitHub, where you can find its installing instructions and a full description.

It already supports many fashionable technologies you might want to use, such as SASS, LESS, CoffeeScript. You are free to write code for your blocks with them and then build it into pages.

    blocks/

        menu/
            menu.sass
            menu.less
            menu.coffee

        tabbed-pane/
            tabbed-pane.sass
            tabbed-pane.coffee

    pages/

        index.html
        index.sass -> index.css
        index.coffee -> index.js

Also it allows extensions. So, if your project needs a specific technology, you can a bit tune building instructions to teach the tools how to work with it.

Moreover, there is no strict requirement to a naming convention and a file structure of your block stack. You are free to intent your own and configure tools to take block code from the right folders or files.

BEM is multi-lingual

I'd like to highlight that BEM methodology is multi technological. You can divide any technology into blocks and then build pages.

For example, equip blocks with their Markdown description and build documentation site for your project block stack automatically.

    blocks/

        menu/
            tabbed-pane.css
            tabbed-pane.js
            tabbed-pane.md

This is what we've done at Yandex for our internal block library.

Also, you can produce HTML output for blocks with templates. And templates are a block technology as well.

    blocks/

        menu/
            tabbed-pane.css
            tabbed-pane.js
            tabbed-pane.md
            tabbed-pane.xsl

For our internal library we also used to use XSL asa templating solution. But not long ago we struggled with XSL for speed and came up with our own JavaScript-based template engine, called BEMHTML.

    blocks/

        menu/
            tabbed-pane.css
            tabbed-pane.js
            tabbed-pane.md
            tabbed-pane.bemhtml

When that happend, we were just to add one more technology into already existing blocks. That was very easy.

BEMHTML

BTW, BEMHML is a pseudo language which can be compiled into ugly but efficient JavaScript.

We, at Yandex, are fans of declarative programming, and borrowed from XSL all it's declarative feature and implemented it with JavaScript speed.
The result can be run on both client or server size. Sometimes we produce HTML output on server under Node.js and sometimes directly in a browser.

If you are insriped, you can check out BEMHTML reference.

Libraries

BEM methodology enables you to create reusable code libraries. That, in turn, allows to develop faster and better.

We, here at Yandex, have a bunch of our in-house BEM-based libraries helping us to build a new Yandex-style web service much faster than from the scratch and making maintaining process easier.

When we started to open source our magic stuff, a small part of the internal library was turned into bem-bl.
bem-bl stands for BEM block library and provides some common blocks for building web interfaces.

All the available blocks are represented in the bem-bl documentation.

Each block is represented by a documentation page where you can find its description and some examples. Significant that all these examples are alive. They are not just screenshots of interface pieces, but iframes showing real pages with blocks.
Using the block page you can try how the block works in your browser and then proceed to the code in order to see how to use it.

Also, you can explore block code since they all are in the GitHub repository.

Such exploration helps when you need to create your own block library.

Examples of BEM libraries

Here there are some libraries implemented with BEM:

  • Bootsrap BL
    The famous bootstrap component stack structured like a BEM library so that BEM tools can work with it.
  • jQueryUI BL
    A set of jQuery-UI components turned into a block library. If you are used to jQuery-UI, you can still use it but with the nice BEM stack.
  • Modernizir BL
    a small repository that represents the Modernizr library, which many of you I'm sure are familiar with, with BEM terms.

How to try?

There is a project skeleton hosted on GitHub, bem-project-stub.
This is a repository that can be a base for your own project using bem-bl, other necessary libraries and, of course, your own blocks. It's README gives all the explanations.
So, this is a cool opportunity to touch BEM stack.

BEM satellite development tools

Besides, BEM team also produces many very nice development tools.

borschik has already been introduced.

Also, you might be interested in CSSO, which is CSS optimizer unlike others. It does usual minification, but what is more, preforms structural optimizations, which no one of existing optimizers can do.

before

    .test1 {
        border: none;
        background-color: red;
    }

    .test2 {
        border: none
    }

    .test3 {
        background-color: #FF000;
    }

after

    .test1, .test2 {
        border: none
    }

    .test1, .test3 {
        background-color: #F00;
    }

These two small pieces of code give a taste how smart CSSO is. Indeed the full list of the transformations it makes on CSS cannot be listed because of it's really huge.

One more optimizer, called SVGO, cleans SVG files from many useless information which different graphic editors leave inside.

Upshort

So, BEM is

  • A methodology about how to code web projects;
  • A toolkit to automate development and optimize production code, and
  • Libraries helping to develop faster and better.

Please address your questions to the comminuty asking in BEM Facebook group or in Twitter @bem_tw.

This information is also available as a talk BEM. What you can borrow from Yandex front-end dev given at WebConf Riga at 10th November 2012.