Pull to refresh

БЭМ, следующий уровень

Reading time 4 min
Views 8.4K
По мотивам статьи на Хабре и флейма вокруг нее. Статья написана для тех кто хочет попробовать БЭМ, но не знает с какой стороны за него взяться. При первом взгляде на БЭМ, он кажется логичным и невероятно удобным. Но при попытке реализовать пользователь сталкивается с препятствиями, которые нивелируют все достоинства. Я не знаю как и почему создавалась эта методология, меня это не парит, если использовать правильно, то это прикольно, я же не задумываюсь для чего когда-то строили автомобиль или самолет, зато сейчас им пользоваться удобно, это же просто удобный инструмент. Знаю только, что при создании, никто не собирался стили и классы писать одним полотном.

Я попытаюсь рассмотреть один из многих вариантов применения методологии БЭМ на практике, который не только соответствует духу, но и рекомендациям создателей.

На мой вгляд главная проблема БЭМ не в сложных и длинных именах, или отсутствии каскада (что кстати не всегда правда). А в непонимании многих зачем им это нужно. Писать и без того сложно читаемый HTML код руками, добавлять монструозные имена класса тем самым еще более нагромождая код, ой как не хотелось. А уж CSS длинной более 3000 строк вообще вызывал рвотные позывы. И только после знакомства с БЭМ инфраструктурой я понял все прелести данного подхода. Здесь мы рассмотрим сам подход оставив в стороне инструменты разработанные создателями БЭМ, чтобы сосредоточиться на самой реализации и глубже понять весь процесс.

Для этого я использовал Node.js, фреймворк Express, установив его со стандартным шаблонизатором Jade и CSS препроцессором Stylus.

Сам проект лежит тут: github.com/jchouse/bem-school_type_middle
Инструкция по запуску в readme.

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

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

Подготовим простой объект с информацией (конечно он может собираться из базы данных, или быть захардкоженным):
routes/index.js
res.render('index', 
    { 
	title: 'BEM средняя школа',
	menu: [
	    {
		url: '#home',
		content: 'Главная'	
	    },
	    {
		url: '#port',
		content: 'Портфолио'	
	    },
...........

ВНИМАНИЕ: информация захардкожена, при изменении, нужно перезапустить сервер. Для чистой верстки можно писать текст в Jade блока, а клиенту отдавать сгенерированный HTML.

Минимум кода в шаблоне страницы, лишь самое необходимое.
views/index.jade
extends ../blocks/page/page

block content
    include ../blocks/content/content


Весь код описания блока по возможности помещать внутри самого блока.
Это обёртка страницы которая остается неизменной (заголовок, футер и т.д.):
blocks/page/page.jade
doctype 5
html
    include ../head/head
    body.page
        div.page__wrapper
            include ../main-menu/main-menu
            block content
            include ../footer/footer

Основное меню:
blocks/main-menu/main-menu.jade
ul.main-menu.main-menu_type_horiz
    each item in menu
        li.main-menu__item
            a(href='#{item.url}')= item.content


В общий CSS мы записываем только импорты, сами стили лежат в соответствующей папке блока.
Общие стили, служит для импорта всех блоков:
public/stylesheets/style.styl
@import '../../blocks/page/page'
@import '../../blocks/main-menu/main-menu'
@import '../../blocks/footer/footer'

Стили одного блока, здесь есть описание самого блока, а также импорты стилей модификаторов и элементов.
blocks/main-menu/main-menu.styl
.main-menu
	margin: 0;
	padding: 0;
	text-align: center;
	list-style-type: none;

// Модификаторы
@import '_type/main-menu_type_horiz'
// Блоки
@import '__item/main-menu__item'

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



Чтобы все это работало я применил внутренние элементы импорта, прописав все зависимости руками.

Префиксы использовать не обязательно. Но можно для блоков, которые не имеют визуального представления или для вспомогательных блоков. Например, блок с переменными или блок чистки потока от флоатов. Сами по себе префиксы родились для того, чтобы с первого взгляда отличить блок от элемента блока, в таких реализациях как XSL. Так как мы прописываем имя стиля целиком — надобность в них отпадает.

И да! Такой подход дает настоящую реюзабельность, копируешь и вставляешь в новый проект папку блока и, вуаля, он уже в твоем проекте. Причем блоки используемые во всех документах можно вынести в blocks-common и копировать между проектами всем скопом. А если еще вступить в предварительный сговор с дизайнером и бекендом, жизнь вообще представляется в розовом цвете.

Минусы:
  1. Вся информация хранится в одном объекте, едином для всей страницы, поэтому блоки не совсем независимые. Нужно внимательно следить за ключами. И лучше сразу все тщательно документировать;
  2. Конечно, очень мешает, что мелкие повторяющиеся блоки (кнопки, например), которых много на странице, но в разном окружении, придется импортировать очень аккуратно. Может быть экран использовать...
  3. Все зависимости пишем ручками. Конечно можно и скриптик для этого написать;
  4. Сейчас модификаторы не влияют на HTML разметку и JS.


Все проблемы решают bem-bl + bem-tools. О том как пользоваться этими двумя инструментами для рядового проекта, расскажем в следующей статье.

UPD: Товарищи минусующие, я понимаю что мои писательские способности далеки от совершенства, и любую конструктивную критику приветствую. Вот только не забывайте ее оставлять в комментариях к статье. Спасибо :)
Tags:
Hubs:
-1
Comments 8
Comments Comments 8

Articles