Денис Крешихин

Денис
Крешихин

iOS-разработчик с 15+ летним опытом

Тимлид/сеньор по обстоятельствам

Интересы: swift, uikit, rxswift, oop/ood, devops, agile

2024 © Денис Крешихин

Хорошие верстальщики отправляются на небеса, а плохие куда захотят. Или — почему БЭМ не приносит счастья?

Все мы привыкли слышать поучительные разговоры о том "как надо верстать", или о том "как не надо". Иногда понятие "как надо" строится на объективных фактах, иногда на фактах которые скрыты где-то в глубине проблемы. Всё вместе это образует некоторые правила вёрстки, которыми и руководствуется верстальщик в своей повседневной работе.

Первоначально правила вёрстки были сродни искусству - ты мог делать что угодно, и никто тебя не останавливал, кроме возможностей веб-браузеров естественно. Потом эти правила превратились в что-то вроде хороших советов для домохозяек. Ты прибегал к тому или иному совету раз от раза, просто что бы сделать свою работу более интересной, почувствовать себя переоткрывателем чего-то. Но это было не обязательно. Вообще это был довольно длительный период веба, но и всё-таки ему настал конец. Появился тренд на догматизацию, свободы становилось всё меньше и меньше - и в какой-то момент появился БЭМ .

Вёрстка должна быть увлекательной

Эту статью мне захотелось написать, после ознакомления со статьёй «Верстка для самых маленьких. Верстаем страницу по БЭМу».

Сразу оговорюсь, что цель моей статьи не научить «верстать правильно», хотя большая часть посвящена именно вёрстке, а дать верстальщикам, разработчикам, дизайнерам и руководителям немного другой взгляд на проблему вёрстки и вообще программирования UI для современного веба.

Начну с того, что являюсь приверженцем тех взглядов, что главное в командной раработке это максимально возможная свобода действий каждого участника разработки. Члены команды не должны чувствовать себя связаны каким-то методологиями, догмами и другими религиозными взглядами. Всё это очень сильно вредит мотивации, которая и является единственным двигателем проекта. По сути руководствуясь только своей мотивацией matz сделал Ruby, Резинг jQuery, а сэр Тим Бернерс-Ли HTML – как мы видим эти проекты до сих играют немаловажную роль в вебе.

Как же повысить мотивацию и развязать руки тем кто работает с фронтендом в веб-проекте и при этом не снизить качество разработки?

Ответ довольно прост – всего этого можно легко добиться делая ставку на современные технологии и тенденции в мировом вебе.

Отказ от HTML в пользу haml/slim/jade делает вёрстку проще и выразительней

Несмотря на то что HTML создавался для облегчения вёрстки и в 1980-е был самым что ни на есть высокоуровневым языком, сейчас ситуация полностью противоположная. HTML стал слишком сложным и специфичным, смысл верстать в HTML такой же, как программировать в машинных кодах, когда под рукой ассемблер.

К тому же в HTML как наследнике SGML изрядно извращена сама идея GML. Для этого можно сравнить примеры вёрстки на GML/HTML/slim.

GML-script, 1969 год.

:h1.Chapter 1:  Introduction
:p.GML supported hierarchical containers, such as
:ol
:li.Ordered lists (like this one),
:li.Unordered lists, and
:li.Definition lists
:eol.
as well as simple structures.
:p.Markup minimization (later generalized and formalized in SGML),
allowed the end-tags to be omitted for the "h1" and "p" elements.

Современный HTML

<h1> Chapter 1: Intruduction </h1>
<ol>
   <li> Ordered lists (like this one),
   <li> Unordered lists, and
   <li> Definition lists
</ol>
<p>as well as simple structures.</p>
<p>Markup minimization (later generalized and formalized in SGML),
   allowed the end-tags to be omitted for the "h1" and "p" elements
</p>

Ruby Slim, 2011

h1 Chapter 1: Intruduction
ol
   li Ordered lists (like this one),
   li Unordered lists, and
   li Definition lists
p as well as simple structures.
p Markup minimization (later generalized and formalized in SGML),
   allowed the end-tags to be omitted for the "h1" and "p" elements

Как видим slim больше соответствует первоначальной идеи GML чем современный HTML. Так что использование современных шаблонизаторов делает код читабельнее и лаконичнее, он одинаково понятен и верстальщику и программисту. В нём легко выделить семантику. Более того, многие шаблонизаторы поддерживают включения и нативного HTML-кода, так что есть возможность делать гибридные шаблоны, особенно если в проекте много унаследованной вёрстки.

Вёрстка является частью экосистемы проекта, нет смысла её отделять

Руководители и заказчики частенько желают видеть результаты вёрстки в отдельных html-файлах. Вёрстка сразу в рабочем проекте кажется им надувательством. Поэтому верстальщики вынуждены копи-пастить десятки раз layout из одного файла в другой что бы получить постраничный html-прототип проекта. Такой подход приводит к тому что в вёрстке содержится куча ошибок в разных файлах и эти ошибки приходится исправлять программистам.

Вёрстка неотделима от проекта. Точно так же как контроллеры неотделимы от видов. Нельзя взять и папочку views из одного проекта и перекинуть в другой, так что бы всё заработало. Поэтому не стоит питать иллюзий и насчёт вёрстки.

Отказ от CSS в пользу LESS/SASS развязывает руки

В CSS заложены довольно строгие ограничения, в частности в нативном CSS нельзя осуществить манипуляции, которые в программировании называют наследованием. Т.е. один класс не может наследовать свойства другого класса, единственный способ распространить один и тот же стиль для разных элементов это создать общий селектор. Так что при программировании стилей всегда приходится выбирать между общностью селекторов и изолированностью стиля. К частью в LESS легко решает проблемы за счёт гибкой системы mixin-ов.

Приведу небольшой пример. Пусть в проекте есть несколько классов элементов одного цвета с одинаковым шрифтом, но при этом имеющие разную семантику и расположенные в разных частях страницы:

/* однотипные классы */
.button{
    background-color: blue;
    color: white;
    font-family: Arial;
    font-size: 12px;
}
.header{
    background-color: blue;
    color: white;
    font-family: Arial;
    font-size: 12px;
}
.footer{
    background-color: blue;
    color: white;
    font-family: Arial;
    font-size: 12px;
}

В LESS можно просто выделить mixin с названием blue-arial-element;

blue-arial-element{
    // в less можно делать строчные комментарии
    // поэтому property желательно писать «в столбик»
    // background-color: black;
    background-color: blue;
    color: white;
    font-family: Arial;
    font-size: 12px;
}

.button{
    .blue-arial-element;
}
.header{
    .blue-arial-element;
}
.footer{
    .blue-arial-element;
}

Более того, этот mixin несмотря на то что и выглядит как класс, не будет засвечен в HTML-коде. Так что если наступит время когда от него придётся избавиться, его можно будет удалить из styles.less без изменения кода HTML. В классическом же решении, классы приходится выковыривать из всех мест где они появляются.

Из таких mixin-ов можно (и нужно) сооружать целые библиотеки стилей, которые позволяют легко переносить стили из одного проекта в другой.

Понимание того что ты делаешь, важнее того как ты это делаешь

Можно ли сходу сказать что происходит в этом html-коде?

<div class="b-company">
    <div class="b-company__header">
          <div class="b-item-head">
            <div class=b-item-head__img>
                <img  src="img/sq.png">
            </div><div class="b-item-head__text">ABOUT WHITESQUARE</div>
        </div>
    </div>
    <div class="b-company__content">
        <div class="b-content">
            <img class="b-content__img" src="img/middle.png"/>
            <div class="b-content__text">
                    In ultricies pellentesque massa a porta. Aliquam
                    ipsum enim, hendrerit ut porta nec, ullamcorper et
                    nulla. In eget mi dui, sit amet scelerisque nunc.
                    Aenean augue arcu, convallis ac vulputate vitae, mollis
                    non lectus. Donec hendrerit lacus ac massa ornare
                    hendrerit sagittis lacus tempor. Vivamus et dui et
                    neque accumsan varius et ut erat.
                    Enean augue arcu, convallis ac ultrices.
            </div>
            <div class="b-content__link">
                <p><a href="#" class="b-link">Read more</a></p>
            </div>
        </div>
    </div>
</div>

Очевидно что этот код немного запутан. Если верить статье упомянутой во введении, то код создаёт небольшую статью с заголовком, фотографией и текстом-описанием. Можно ли сделать эту вёрстку лучше? Наверное было бы лучше если бы не приходилось тратить время на её расшифровку. Другими словами, это выглядело бы примерно так:

article
    div.title
        h1 About whitesquare
        div.filler &nbsp;
    figure: img width="136" height="136" alt="" src="sample.png"
    p
        | Lorem ipsum dolor sit amet, consectetur adipiscing elit.
        | Pellentesque dictum metus ligula, vitae bibendum augue
        | fermentum non. Fusce euismod libero eu lectus scelerisque
        | hendrerit. Nam vel fermentum tellus, vel lobortis felis.
        | Phasellus dolor ipsum, vehicula ac justo quis,
        | scelerisque tempus nibh.
        a Read more

Оказывается, что вёрстка может говорить сама за себя. И нет никаких препятствий что бы не делать её такой. Можно много времени уделять разговорам о повторном использовании кода, но все эти разговоры не имеют большого значения если на выходе получается нечитабельный код. Сложный разросшийся код это явный признак того, что в проекте что-то не так. И нет причин, что бы в вёрстке веб-проектов были какие-то другие принципы. Верстальщики такие же люди как и программисты, никто не любит чувствовать дискомфорт на своём рабочем месте. К тому же разросшаяся вёрстка доставляет страдание всем — и верстальщикам, и программистам.

BEMLESS, или верстаем как хочется

Представим на некоторое время что не существует никаких правил вёрстки и подобных ограничений. У нас есть только макет, тот же Corporate Blue и сервер Sinatra со следующими настройками:

Gemfile

source 'https://rubygems.org'

ruby '1.9.3'

gem 'sinatra'
gem 'slim'
gem 'therubyracer'
gem 'less'

config.ru

require './app'
run Sinatra::Application

И само приложение app.rb

require 'sinatra'
require 'slim'
require 'less'

set :views, :less => 'assets/stylesheets', :default => 'views'

helpers do
  def find_template(views, name, engine, &block)
    _, folder = views.detect { |k,v| engine == Tilt[k] }
    folder ||= views[:default]
    super(folder, name, engine, &block)
  end
end

get '/' do
  slim :index
end

get '/:style.css' do
  less params[:style].to_sym
end

get '/:image.png' do
  send_file File.join(settings.root, "assets/images/#{params[:image]}.png")
end

Как видно, настройки проекта и сам проект занимает намного меньше кода чем типичный html-заголовок.

В проекте три хука, первый для индекс-страницы которая называется index.slim и лежит в папке views, второй и третий подгружают ресурсы вида *.css и *.png из соответствующих папок. (Чуть ниже будут приведены ссылки и на github проект готовый к отправке на heroku.) В общем проект в sublime выглядит примерно так:
image

Теперь пришло время обратиться к макету:
image

Я не буду акцентироваться на том, что и как надо верстать, просто буду описывать шаг за шагом что я вижу в slim-код.

Вёрстка каркаса страницы

Сначала необходимо добавить заголовки (обычно они лежат в layout, но т. к. приложение одностраничное, то запишу прям в index.slim):

doctype html
html
    head
        meta charset="utf-8"
        title Whitesquare
        link rel="stylesheet" href="/styles.css"
        link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Oswald:400,300"
        /[if lt IE 9]
            script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"

Затем я вижу следующие элементы: хедерлайн и хедер. Это верхняя часть сайта. Заверстаю её в том порядке как и в макете:

hr
header
    a.logo href="/": img src="logo.png"
    div.search
        input type="text" placeholder="Search"
        div.button Go

Как нетрудно заметить, это несколько лаконичнее чем в БЭМ:

<div class="b-page__line">
    <div class="b-head">
        <div class="b-head__logo">
            <div class="b-logo">
                <a href="#"><img class="b-logo__img" src="img/Logo.png"/></a>
            </div>
        </div>
        <div class="b-head__search">
            <div class="b-search">
                <div class="b-search__input">
                    <input type="text" class="b-input b-input_search" placeholder="Search">
                </div><div class="b-search__input"><div class="b-button">GO</div>
                </div>
            </div>
        </div>
    </div>
</div>

Далее следует навбар и слайдер. Вёрстка по тому же принципу — для навбара берётся элемент nav, список оформляется в список, ссылки в ссылки. Т.е. вёрстка становится средством описания иерархии элементов, то что находится внутри должно вкладываться, то что находится рядом должно быть рядом. Все элементы отражают ровно то, что увидит потом конечный пользователь. Если такого элемента нет, то используется наиболее близкий по семантике с соответствующим классом.

nav
    ul
        li: a href="#" Home
        li: a.active href="#" About us
        li: a href="#" Services
        li: a href="#" Partners
        li: a href="#" Projects
        li: a href="#" Careers
        li: a href="#" Contact
div.slider
    div.screen
    ul
        li
            div.index 1
            div.title Lorem ipsum dolop
        li.active
            div.index 2
            div.title Ultricies peletesque
        li
            div.index 3
            div.title Aliquam ipsum
        li
            div.index 4
            div.title Nullam sed maurus ut

После навбара идёт главный блок со статьями:

div.main
    div.big-news
        article
            div.title
                h1 About whitesquare
                div.filler &nbsp;
            figure: img width="136" height="136" alt="" src="sample.png"
            p
                | Lorem ipsum dolor sit amet, consectetur adipiscing elit.
                | Pellentesque dictum metus ligula, vitae bibendum augue
                | fermentum non. Fusce euismod libero eu lectus scelerisque
                | hendrerit. Nam vel fermentum tellus, vel lobortis felis.
                | Phasellus dolor ipsum, vehicula ac justo quis, scelerisque
                | tempus nibh.
        article
            div.title
                h1 A word from our CEO
                div.filler &nbsp;
            figure: img width="136" height="136" alt="" src="sample.png"
            p: i
                | "Lorem ipsum dolor sit amet, consectetur adipiscing elit.
                | Pellentesque dictum metus ligula, vitae bibendum augue
                | ermentum non. Fusce euismod libero eu lectus scelerisque
                | hendrerit. Nam vel fermentum tellus, vel lobortis felis.
                | Phasellus dolor ipsum, vehicula ac justo quis, scelerisque
                | tempus nibh."
            p Yane Naumovski, CEO
    div.news
        article
            div.title
                h1 Service
                div.filler &nbsp;
            p
                | Lorem ipsum dolor sit amet, consectetur adipiscing elit.
                | Pellentesque dictum metus ligula, vitae bibendum augue
                | fermentum non. Fusce euismod libero eu lectus scelerisque
                | hendrerit. Nam vel fermentum tellus, vel lobortis felis.
                | Phasellus dolor ipsum, vehicula ac justo quis, scelerisque
                | tempus nibh. Lorem ipsum dolor sit amet, consectetur
                | adipiscing elit. Pellentesque dictum metus ligula, vitae
                | bibendum augue fermentum non. Fusce euismod libero eu
                | lectus scelerisque hendrerit. Nam vel fermentum tellus,
                | vel lobortis felis. Phasellus dolor ipsum, vehicula ac
                | justo quis, scelerisque tempus nibh.
        article
            div.title
                h1 Our teams
                div.filler &nbsp;
            figure: img width="36" height="36" alt="" src="sample.png"
            p
                | Lorem ipsum dolor sit amet, consectetur adipiscing elit.
                | Pellentesque dictum metus ligula, vitae bibendum augue
                | fermentum non.
            figure: img width="36" height="36" alt="" src="sample.png"
            p
                | Lorem ipsum dolor sit amet, consectetur adipiscing elit.
                | Pellentesque dictum metus ligula, vitae bibendum augue
                | fermentum non.
            figure: img width="36" height="36" alt="" src="sample.png"
            p
                | Lorem ipsum dolor sit amet, consectetur adipiscing elit.
                | Pellentesque dictum metus ligula, vitae bibendum augue
                | fermentum non.
        article
            div.title
                h1 24/7/365 SUPPORT
                div.filler &nbsp;
            p
                | Lorem ipsum dolor sit amet, consectetur adipiscing elit.
                | Pellentesque dictum metus ligula, vitae bibendum augue
                | fermentum non. Fusce euismod libero eu lectus scelerisque
                | hendrerit. Nam vel fermentum tellus, vel lobortis felis.
                | Phasellus dolor ipsum, vehicula ac justo quis, scelerisque
                | tempus nibh.
    div.clients
        div.title
            h1 Our Clients
            div.filler &nbsp;
        a href="#": img alt="client1" src="client1.png"
        a href="#": img alt="client2" src="client2.png"
        a href="#": img alt="client3" src="client3.png"
        a href="#": img alt="client4" src="client4.png"
        a href="#": img alt="client5" src="client5.png"
        a href="#": img alt="client6" src="client6.png"
        a href="#": img alt="client7" src="client7.png"

Этот участок кода уже выглядит намного более запутанным, но это конечно поверхностное впечатление, из-за большого количества текста и однотипных элементов, в production или при наличии fake-генераторов (что сейчас являются довольно распространённой практикой) код будет выглядеть намного симпатичнее:

div.main
    div.big-news
        article
            div.title
                h1=@about.title
                div.filler &nbsp;
            figure: img width="136" height="136" alt="" src=@about.photo
            p=@about.text
        article
            div.title
                h1=@ceo.title
                div.filler &nbsp;
            figure: img width="136" height="136" alt="" src=@ceo.photo
            p: i=@ceo.quote
            p=@ceo.name
    div.news
        article
            div.title
                h1=@service.title
                div.filler &nbsp;
            p=@service.text
        article
            div.title
                h1 Our teams
                div.filler &nbsp;
            - @team.each do |emp|
                figure: img width="36" height="36" alt="" src=emp.photo
                p=emp.title
        article
            div.title
                h1 24/7/365 SUPPORT
                div.filler &nbsp;
            p=@support.text
    div.clients
        div.title
            h1 Our Clients
            div.filler &nbsp;
        - @clients.each do |client|
            a href="#": img alt=client.title src=client.logo

Теперь сравним с тем, что предлагает БЭМ:

<div class="b-page__line">
    <div class="b-main">
        <div class="b-main__item">
            <div class="b-company">
                <div class="b-company__header">
                    <div class="b-item-head">
                        <div class=b-item-head__img>
                            <img  src="img/sq.png">
                        </div><div class="b-item-head__text">ABOUT WHITESQUARE</div>
                    </div>
                </div>
                <div class="b-company__content">
                    <div class="b-content">
                        <img class="b-content__img" src="img/middle.png"/>
                        <div class="b-content__text">
                            In ultricies pellentesque massa a porta. Aliquam ipsum
                            enim, hendrerit ut porta nec, ullamcorper et nulla. In
                            eget mi dui, sit amet scelerisque nunc. Aenean augue arcu,
                            convallis ac vulputate vitae, mollis non lectus. Donec
                            hendrerit lacus ac massa ornare hendrerit sagittis lacus
                            tempor. Vivamus et dui et neque accumsan varius et ut erat.
                            Enean augue arcu, convallis ac ultrices.
                        </div>
                        <div class="b-content__link">
                            <p><a href="#" class="b-link">Read more</a></p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="b-main__item">
            <div class="b-company">
                <div class="b-company__header">
                    <div class="b-item-head">
                        <div class="b-item-head__img">
                            <img src="img/sq.png">
                        </div>
                           <div class="b-item-head__text">A WORD FROM OUR CEO</div>
                    </div>
                </div>
                <div class="b-company__content">
                    <div class="b-content">
                        <img class="b-content__img" src="img/middle.png"/>
                        <div class="b-content__text">
                            In ultricies pellentesque massa a porta. Aliquam
                            ipsum enim, hendrerit ut porta nec, ullamcorper
                            et nulla. In eget mi dui, sit amet scelerisque
                            nunc. Aenean augue arcu, convallis ac vulputate
                            vitae, mollis non lectus. Donec hendrerit lacus
                            ac massa ornare hendrerit sagittis lacus tempor.
                            Vivamus et dui et neque accumsan varius et ut erat.
                            Enean augue arcu, convallis ac ultrices.
                        </div>
                        <div class="b-content__link">
                            <p>Yane Naumoski, CEO</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="b-main__item b-main__item_small">
            <div class="b-company">
                <div class="b-company__header">
                    <div class="b-item-head">
                        <div class="b-item-head__img">
                            <img  src="img/sq.png">
                        </div><div class="b-item-head__text  ">SERVICES</div>
                    </div>
                </div>
                <div class="b-company__content">
                    <div class="b-content">
                        <div class="b-content__text">
                            In ultricies pellentesque massa a porta. Aliquam
                            ipsum enim, hendrerit ut porta nec, ullamcorper
                            et nulla. In eget mi dui, sit amet scelerisque
                            nunc. Aenean augue arcu, convallis ac vulputate
                            vitae, mollis non lectus. Donec hendrerit lacus
                             ac massa ornare hendrerit sagittis lacus tempor.
                              Vivamus et dui et neque accumsan varius et ut
                              erat. Enean augue arcu, convallis ac ultrices.
                        </div>
                        <div class="b-content__link">
                           <p><a href="#" class="b-link">Read more</a></p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="b-main__item b-main__item_small">
            <div class="b-company">
                <div class="b-company__header">
                    <div class="b-item-head">
                        <div class="b-item-head__img">
                            <img src="img/sq.png">
                        </div><div class="b-item-head__text  ">OUR TEAM</div>
                    </div>
                </div>
                <div class="b-company__content">
                    <div class="b-content">
                        <div class="b-context__team">
                            <ul class="b-team">
                               <li class="b-team__item">
                                   <div class="b-teammate">
                                       <img class="b-teammate__img" src="img/small.png">
                                       <div class="b-teammate__head">
                                           Lorem Ipsum
                                       </div>
                                       <div class="b-teammate__text">
                                        In ultricies pellentesque massa a porta.
                                        Aliquam ipsum enim, hendrerit ut porta nec
                                       </div>
                                   </div>
                               </li>
                                <li class="b-team__item">
                                   <div class="b-teammate">
                                       <img class="b-teammate__img" src="img/small.png">
                                       <div class="b-teammate__head">
                                           Lorem Ipsum
                                       </div>
                                       <div class="b-teammate__text">
                                           In ultricies pellentesque massa a porta.
                                           Aliquam ipsum enim, hendrerit ut porta nec
                                       </div>
                                   </div>
                               </li>
                                <li class="b-team__item">
                                   <div class="b-teammate">
                                       <img class="b-teammate__img" src="img/small.png">
                                       <div class="b-teammate__head">
                                           Lorem Ipsum
                                       </div>
                                       <div class="b-teammate__text">
                                           In ultricies pellentesque massa
                                           a porta. Aliquam ipsum enim,
                                           hendrerit ut porta nec
                                       </div>
                                   </div>
                               </li>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="b-main__item b-main__item_small">
            <div class="b-company">
                <div class="b-company__header">
                    <div class="b-item-head">
                        <div class="b-item-head__img">
                            <img src="img/sq.png">
                        </div><div class="b-item-head__text  ">24/7/365 SUPPORT</div>
                    </div>
                </div>
                <div class="b-company__content">
                    <div class="b-content">
                        <div class="b-content__text">
                            In ultricies pellentesque massa a porta.
                            Aliquam ipsum enim, hendrerit ut porta nec,
                             ullamcorper et nulla. In eget mi dui,
                             sit amet scelerisque nunc. Aenean augue
                             arcu, convallis ac vulputate vitae, mollis
                             non lectus. Donec hendrerit lacus ac massa
                             ornare hendrerit sagittis lacus tempor.
                             Vivamus et dui et neque accumsan varius
                             et ut erat. Enean augue arcu, convallis
                             ac ultrices.
                        </div>
                        <div class="b-content__link">
                           <p><a href="#" class="b-link">Read more</a></p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="b-main__item b-main__item_long">
            <div class="b-company">
                <div class="b-company__header">
                    <div class="b-item-head">
                        <div class="b-item-head__img">
                        <img  src="img/sq.png">
                        </div><div class="b-item-head__text  ">OUR CLIENTS</div>
                        <div class="b-item-head__white-space"></div>
                    </div>
                </div>
                <div class="b-company__content">
                    <div class="b-companies">
                        <img class="b-companies__img" src="img/middle.png">
                        <img class="b-companies__img" src="img/middle.png">
                        <img class="b-companies__img" src="img/middle.png">
                        <img class="b-companies__img" src="img/middle.png">
                        <img class="b-companies__img" src="img/middle.png">
                        <img class="b-companies__img" src="img/middle.png">
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class=g-clear></div>
</div>

Здесь я думаю комментарии излишни. Остался футер, его верстаю в такой же манере:

footer
    div.info
        div.twitter-feed
            h1 Twitter feed
            p
                a href="#" 23 oct
                br
                | Fusce euismod libero eu lectus scelerisque
                | hendrerit. Nam vel fermentum tellus, vel
                | lobortis felis. Phasellus dolor ipsum,
                | vehicula ac justo quis, scelerisque tempus nibh.
        div.sitemap
            h1 Sitemap
            div.column
                a href="#" Home
                a href="#" About
                a href="#" Service
            div.column
                a href="#" Partners
                a href="#" Support
                a href="#" Contact
        div.social-networks
            h1 Social networks
            div.big-icons
                a.twitter href="#": img alt="twitter logo" src="social-twitter.png"
                a.facebook href="#": img alt="facebook logo" src="social-facebook.png"
                a.gplus href="#": img alt="gplus logo" src="social-gplus.png"
            div.small-icons
                a.vimeo href="#": img alt="vimeo logo" src="social-vimeo.png"
                a.flickr href="#": img alt="flickr logo" src="social-flickr.png"
                a.inst href="#": img alt="instagram logo" src="social-inst.png"
                a.rss href="#": img alt="rss logo" src="social-rss.png"

        div.credits
            a.logo href="#": img src="footer-logo.png" alt="Whitesquare logo"
            p
                | Copyright &copy; 2012 Whitesquare. A
                a href="http://pcklab.com" &nbsp;pcklab&nbsp;
                | creation

Описание стилей

Без стилей страница будет выглядеть почти plain text. Теперь пришло время описать стили, для этого можно создать styles.less и накидать иерархию, которая будет более-менее соответствовать иерархии в html.

Первончально это может выглядеть примерно так (листинг styles.less):

.whitesquare{
    hr{}
    header{
        a.logo{}
        .search{
            input{}
            .button{}
        }
    }
    nav{
        ul{
            li{
                a{}
            }
        }
    }
    div.slider{
        .screen{}
        ul{
            li{
                .index{}
                .title{}
                &.active{
                    .index{}
                    .title{}
                }
            }
        }
    }
    .main{
        .big-news{
            article{}
        }
        .news{
            article{
            }
            .clearfix;
        }
        .clients{
            .title{}
            a{}
        }
    }
    footer{
        .info{
            h1{}
            p{}
            .twitter-feed{}
            .sitemap{}
            .social-networks{}
            .credits{}
        }
    }
}

Т.е. создаётся less-файл который задаёт структуру шаблона, от расположения того или иного элемента в иерархии этой структуры зависит стили которые он унаследует или нет.

Далее я могу сказать, что эта страница имеет некоторый зернистый фон, и описать соответствующим образом CSS-свойства, например так:

.gray-noise{
    background-color: #f7f7f7;
    color: #8f8f8f;
    background: url("bg.png");
}

А хедерлайн растянут на всю страницу и имеет некоторую толщину:

.full-width{
    margin: 0;
    width:100%;
}

.thick-headerline{
    height:5px;
    background-color:#7e7e7e;
}

Все эти классы помещаются в helpers.less, а в самом файле styles.less они добавляются как mixin'ы

.whitesquare{
    .full-width;
    .gray-noise;
    .tahoma-font;

    hr{
        .full-width;
        .thick-headerline;
    }
}

Такую операцию можно провернуть не только с цветами, но и со сложными элемантами используя параметрические mixin'ы. Например для маленьких и больших figure можно использовать один mixin с параметром @size:

.custom-figure(@size){
    margin-top: 0px;
    margin-left: 0px;
    margin-right: 10px;
    display: block;
    width: @size; height: @size;
    float: left;
    background-color: @light-gray;
    border: 1px solid #c9c9c9;
    img{
        margin: 1px;
    }
}

Теперь в styles.less это обеспечит отображение как маленьких картинок, так и больших:

.big-news{
    article{
        float: left;
        width: 50%;

        .title{
            .complex-title;
        }
        figure{
            .custom-figure(138px);
        }
        p{
            margin-right: 10px;
        }
    }
}

.news{
    article{
        float: left;
        width: 33.3333%;

        .title{
            .complex-title;
        }
        figure{
            .custom-figure(38px);
        }
        p{
            margin-right: 10px;
        }
    }
    .clearfix;
}

Таким образом, файл styless.less начинает играть туже роль что контроллеры в MVC-проекты, появляется возможность варьировать стиль элемента без переписывания стилей или изменения вёрстки. Полный листинг стилей можно посмотреть на bitbucket https://bitbucket.org/kreshikhin/bemless, а результат на heroku http://bemless.herokuapp.com/ Т.к. целью статьи было показать преимущества свободного подхода, то я не стал добиваться идеальной вёрстки, и там есть ещё над чем работать.

И снова БЭМ

Теперь не лишним будет детально разобраться в чём конкретно заключаются недостатки БЭМ и в чём преимущества современной вёрстки на шаблонизаторах с css-препроцессором. Для этого проанализируем цели декларируемые в описании методологии http://ru.bem.info/method/

1. Типовые проекты должны разрабатываться быстро, но жить долго. Нужно уметь за короткий срок создать проект, архитектура которого позволит без труда поддерживать и развивать его долгие годы.

БЭМ не позволяет создавать что-то быстро, но заставляет писать очень много лишнего кода. Каждый БЭМ-класс должнен удовлетворять куче требований, которые могут быть не связаны с семантикой класса, а лишь отражать его положение в структуре. Таким образом, верстальщик берёт на себя часть работы компьютера. Цель же любой команды - максимально автоматизировать процесс разработки, что бы каждый её участник мог наилучшим образом реализовать свой творческий потенциал.

Использование современных шаблонизаторов и css-прероцессоров куда лучше позволяет решать эту задачу.

2. Над проектом работает много людей. Нужно уметь эффективно организовывать работу команд, как из двух разработчиков, так и из десятков.

Веб является миром инноваций и творчества. Единственный путь добиться хороших результатов от творческих работников заключается в предоставлении им максимальной свободы действия. БЭМ ограничивает свободу, в то время как современные инструменты разработки направлены на эмансипацию труда: системы контроля версий позволяют одновременно редактировать один файл нескольким разработчикам; системы непрерывной интеграции позволяют отсеивать креш-коммиты; таск-менеджеры планировать работу даже для людей в разных временных поясах. БЭМ наоборот – идёт против тренда, накладывая только ограничения и не представляя никакой свободы компенсирующей эти ограничения.

3. Масштабируемость команд. Добавление новых людей в команду должно улучшать производительность команды. Необходима возможность быстро вводить новых разработчиков в курс дела и выделять им собственные зоны ответственности. Для того, чтобы с одним и тем же кодом можно было работать долгое время и разным составом команды, код должен быть хорошо структурирован.

Масштабируемость лучше всего достижима в том случае, если от кандидатов не требуется каких-то дополнительных знаний. Современные шаблонизаторы и препроцессоры интуитивно понятны, в отличии от чистого HTML и CSS. БЭМ кроме этого требует ещё и соблюдения внутренней бюрократии.

Бюрократия же не масштабируема по определению.

4. Повторное использование кода. Каждый новый проект или элемент интерфейса не должны писаться с нуля. Если где-то внутри компании уже выполнялась похожая задача, нужно максимально повторно использовать полученный в результате код. У кода не должно быть контекстной зависимости, его нужно уметь легко переносить в другое место.

БЭМ принципиально не позволяет использовать код повторно, если понимать повторное использование в классическом смысле. Единственное что позволяет делать БЭМ это копипастить, бессмысленно и беспощадно. Современные css-препроцессоры позволяют создавать целые библиотеки для повторного использования на основе миксинов, которые способны играть такую же роль как функции и классы в языках общего назначения.

Выводы

Свобода действий в командной разработке и приверженность современным технологиям гораздо важнее чем какие-либо методологии. Вместе с CSS-препроцессором типа LESS и на современном шаблонизаторе вроде slim легко решаются абсолютно все проблемы, которые призван решить БЭМ. При этом качество проекта намного возрастает:

  • можно использовать чистую семантическую вёрстку в т.ч. HTML5, не плодя лишних классов
  • вёрстка лаконична и читабельна
  • есть возможность создавать библиотеки для повторного использования css-кода
  • стили и элементы не имеют жёсткой привязки, стили можно подстраивать не меняя названия класса
  • вёрстка готова к интеграции в проект, без переделки под шаблонизатор
  • у верстальщика развязаны руки, нет методологических ограничений
  • данные технологии легко вписываются в демократически организованные команды

Этот список конечно не полный, в html и css вёрстке накопилось столько проблем, что их все не получится обсудить в одной статье.

В любом случае выбор за вами, сидеть на БЭМ или двигаться дальше.

bemless на heroku

bemless на bitbucket