- PVSM.RU - https://www.pvsm.ru -

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

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

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

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

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

Сразу оговорюсь, что цель моей статьи не научить «верстать правильно», хотя большая часть посвящена именно вёрстке, а дать верстальщикам, разработчикам, дизайнерам и руководителям немного другой взгляд на проблему вёрстки и вообще программирования 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>
<p>
<ol>
   <li> Ordered lists (like this one),</li>
   <li> Unordered lists, and</li>
   <li> Definition lists</li>
</ol>
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
p: ol
   li Ordered lists (like this one),
   li Unordered lists, and
   li Definition lists
  | 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>
        </div>
</div>

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

article
	div.title
		h1 About whitesquare
		div.filler  
	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

Я не буду акцентироваться на том, что и как надо верстать, просто буду описывать шаг за шагом что я вижу в 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" type="text/css"
		/[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  
					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  
					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 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."
					p Yane Naumovski, CEO
			div.news
				article
					div.title
						h1 Service
						div.filler  
					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  
					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  
					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  
				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  
					figure: img width="136" height="136" alt="" src=@about.photo
					p=@about.text
				article
					div.title
						h1=@ceo.title
						div.filler  
					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  
					p=@service.text
				article
					div.title
						h1 Our teams
						div.filler  
					- @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  
					p=@support.text
			div.clients
				div.title
					h1 Our Clients
					div.filler  
				- @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 © 2012 Whitesquare. A 
						a href="http://pcklab.com"  pcklab 
						| 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 [2]:

.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-проекты, появляется возможность варьировать стиль элемента без переписывания стилей или изменения вёрстки.
Полный листинг стилей можно посмотреть на github github.com/kreshikhin/bemless [3], а результат на heroku bemless.herokuapp.com/ [4]
Т.к. целью статьи было показать преимущества свободного подхода, то я не стал добиваться идеальной вёрстки, и там есть ещё над чем работать.

И снова БЭМ

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

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

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

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

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

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

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

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

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

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

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

Выводы

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

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

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

Автор: kreshikhin

Источник [6]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/news/49419

Ссылки в тексте:

[1] «Верстка для самых маленьких. Верстаем страницу по БЭМу»: http://habrahabr.ru/post/203440/

[2] size: http://habrahabr.ru/users/size/

[3] github.com/kreshikhin/bemless: https://github.com/kreshikhin/bemless

[4] bemless.herokuapp.com/: http://bemless.herokuapp.com/

[5] ru.bem.info/method/: http://ru.bem.info/method/

[6] Источник: http://habrahabr.ru/post/203838/