Шаблоны, препроцессоры, jQuery

Автор учебного курса: Медведский Максим Константинович, студент гр. ИТб-401 ФГАОУ ВО «РГППУ.

Скачать Notepad++ Portable
Скачать Sublime Text 3 Portable
Скачать материалы к учебному курсу -
папка kurs_prepros.zip (2,5 Мб)




Теория 1. БЭМ-методология

Цель: изучить методологию БЭМ

Задачи:

  • узнать, что такое блок, элемент, модификатор;
  • ознакомиться с принципами структурирования кода.
Рисунок 1.1

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

Принципы БЭМ-методологии

Разработчики из Яндекс сформулировали следующие принципы будущей методологии:

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

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

История развития БЭМ

Обычно CSS времен становления Яндекса (примерно 2005 год) содержал длинный каскад стилей. Каждый блок кода описывался отдельно. Внешний вид элементов был сопряжен с их позиционированием на странице. Например:

Пример старого кода

<div class=”btn”>
    <a href = ”#”>Кнопка<a>
</div>

.btn {
	font-size: 18px;
	text-transform: uppercase;
	line-height: 1.6;
	margin: 15px;
	padding: 10px;
}

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

Основы БЭМ-методологии

Технологии (HTML, CSS, JavaScript), которые использовал Яндекс, изменялись в зависимости от требований проекта, а принципы БЭМ должны были быть универсальны.

Они сформулировали основные правила, по которым будут развивать свои проекты, и которые никак не будут зависеть от технологий и инструментов.

Чтобы ускорить разработку, необходимо было облегчить поддержку HTML и CSS отдельных компонентов страницы, сделать код менее связанным. Для этого разбили страницу на части. Так появилось новое понятие — блок. Блок мог состоять из различных элементов, которые не использовались вне самого блока. Состояния и поведение блока и элемента можно было задавать с помощью модификатора.

Это были три ключевых понятия, на которых основывалось большинство правил. Аббревиатура от трех слов Блок, Элемент и Модификатор стала названием методологии — БЭМ.

Блок

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

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

Рисунок 1.2 - Блок

Элемент

Часть блока, которая не может использоваться в отрыве от него и имеет смысл только в рамках своего родителя. Элементы могут быть обязательными и опциональными.

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

Рисунок 1.3 - Элемент

Модификатор

Свойство блока или элемента, которое меняет их внешний вид, состояние или поведение.

Модификатор имеет имя и может иметь значение. Использование модификаторов опционально. У блока/элемента может быть несколько разных модификаторов одновременно.

Так, например, с помощью модификатора можно изменить не только цвет меча, но и его функциональность (как показано в случае с красным мечом):

Рисунок 1.4 - Модификатор

Правила именования CSS-селекторов

Все принципы БЭМ формировались и внедрялись постепенно. Началось с того, что были сформулированы жесткие правила именования CSS-селекторов.

По БЭМ-методологии блоки не уникальны и их всегда можно использовать повторно, поэтому в описании CSS-правил отказались от использования id.

Блок не должен зависеть от окружающих его блоков и сам не должен влиять на соседние блоки, поэтому в CSS отказались от:

  • тегов;
  • вложенных селекторов;
  • глобального сброса правил для всей страницы.

Важной определяющей сущностью в именовании селекторов стал блок:

  • полное имя элемента/модификатора формируется так, чтобы из него можно было определить принадлежность данного элемента/модификатора к конкретному блоку;
  • по имени модификатора элемента должно быть возможно определить принадлежность данного модификатора к конкретному элементу конкретного блока.

Правила формирования имени БЭМ-сущности

  • каждая БЭМ-сущность должна иметь свой класс;
  • CSS-свойства для блоков, элементов и модификаторов описываются только через классы;
  • для разделения слов в именах используется дефис (-);
  • элемент отделяется от блока двумя подчеркиваниями (__). Модификатор — одним (_);
  • имена БЭМ-сущностей записываются с помощью цифр и латинских букв в нижнем регистре.

Пример

Имя блока — header.

Имя элемента блока — header__search-form — элемент search-form блока header.

Имя модификатора блока — header_theme_green-forest — модификатор theme в значении green-forest блока header.

Имя модификатора элемента — header__search-form_disabled — булев модификатор disabled элемента search-form блока header.

Пример

HTML
<div class="header header_theme_green-forest">...</div>

CSS
.header { color: red; }

БЭМ в HTML

Пример

В HTML каждая БЭМ-сущность определяется своим классом
<div class="block-name">
  <div class="block-name__elem"></div>
     ...
</div>

В простейшем случае блок соответствует DOM-узлу, один к одному. Но DOM-узел и блок — это не всегда одно и то же. На одном DOM-узле может совмещаться несколько сущностей. Это называется миксом.

С помощью миксов можно:

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

Пример

В проекте кнопки реализованы блоком button. Необходимо поместить кнопку в форму поиска (search-form) и задать для кнопки отступы. Для этого воспользуемся миксом блока button и элемента button блока search-form:
<div class="search-form">
  <div class="button search-form__button"></div>
</div>

Микс позволяет использовать универсальную кнопку, которая ничего не знает об отступах от границ конкретной формы. В данном случае в форме поиска есть элемент search-form__button, который знает, где ему надо находиться, и блок button, который нужно отображать.

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

Организация файловой системы

Яндекс устраивала первоначальная структура проекта в файловой системе: в ней было сложно ориентироваться и находить нужные технологии сущностей.

Что хотелось получить от новой структуры:

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

Можно было бы разделить репозиторий проекта по технологиям:

Пример структуры репозитория

css/
html/
js/
xml/
xsl/

Такой подход не показал кардинальных изменений. Поэтому было решено вынесли общую часть кода, подходящую для всех проектов и платформ, в отдельную директорию common. Специфические реализации, необходимые только определённым проектам, складываются отдельно — в директорию service. А примеры — в директорию example.

Пример правильной структуры репозитория

common/
  css/
  js/
  xml/
  xsl/
example/
  html/
service/
  auto/
    css/
    xml/

Так можно быстрее находить нужный код для отдельных проектов. Но эта структура всё равно не отвечала всем требованиям.

Блоки первичны, технологии — вторичны

Чтобы создать нужную структуру проекта и реализовать цели, которые Яндекс перед собой ставил, они вывели на передний план блоки, а не технологии.

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

Что это дает

Ускорение разработки
  • блоки могут использоваться повторно;
  • реализация блоков может быть изменена на новом уровне переопределения, не затрагивая при этом базовую функциональность и стили;
  • блок — независимый компонент страницы и в его директории находится всё, что необходимо для корректного функционирования. Поэтому блоки легко переносить из проекта в проект, достаточно просто скопировать директорию блока.
Ускорение рефакторинга
  • разработчик работает c небольшими блоками кода;
  • технологии реализации одного блока не связаны с технологиями другого;
  • одинаковая структура репозитория позволяет быстро ориентироваться в проекте и находить нужные файлы.
Универсальная расширяемая система
  • появились уровни переопределения;
  • количество технологий не ограничено. Любая новая технология реализации находится в файле конкретного блока;

Технологии реализации

Был придуман новый термин — технология реализации.

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

Для реализации блока используются различные технологии, например:

  • поведение — JavaScript, CoffeeScript;
  • внешний вид — CSS, Stylus, Sass;
  • шаблоны — Jade, Handlebars, XSL, BEMHTML, BH;
  • документация — Markdown, Wiki, XML.

Выбор технологий реализации не ограничен, разве только требованиями проекта.

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

Всё в проекте перестраивается относительно этого нового принципа. Блок становится ключевым понятием БЭМ. Соответственно, изменяется и структура файловой системы.

Правила организации файловой системы БЭМ-проекта

  • блок — отдельная директория в файловой системе. Имя блока и его директории совпадают;
  • реализация блока разделяется на отдельные файлы;
  • файлы, относящиеся к блоку, всегда находятся в его директории;
  • опциональные элементы и модификаторы выносятся в отдельные файлы;
  • проект разделяется на уровни переопределения.

Пример файловой системы

blocks/
  input/                     # Директория блока input
    _theme/                  # Директория опционального модификатора theme
      input_theme_forest.css # Реализация модификатора theme в значении forest в технологии CSS
    __clear/                 # Директория опционального элемента clear
      input__clear.css       # Реализация элемента clear в технологии CSS
      input__clear.png       # Реализация элемента clear в технологии PNG
    input.css                # Блок input в технологии CSS
    input.js                 # Блок input в технологии JavaScript
  button/                    # Директория блока button
    button.css
    button.js
    button.png

Уровень переопределения

Уровнем переопределения стали называть директории с реализацией блоков. Появление уровней позволило изменять реализацию блока, добавляя новые свойства (доопределять) или изменяя старые (переопределять) на другом уровне. Конечная реализация блока собирается со всех уровней последовательно.

Уровни переопределения позволяют:

  • подключать библиотеки и обновлять их, не делая правок в коде;
  • выделять общие части реализаций блоков на один уровень, а частные случаи (например, специфическую реализацию для отдельных сервисов) — на другой;
  • разделять проект на платформы. Общую реализацию для всех платформ хранить на одном уровне, а платформо-специфичную — выносить на другой;
  • избежать копирования кода и создания новых сущностей, если необходимо изменить уже существующую функциональность.

Если сравнить уровни со слоями, то базовый слой – это исходная реализация блока, а каждый последующий слой накладывается сверху и дополняет (наследует) или изменяет базовую реализацию.

Рисунок 1.5 - Слои

Пример уровней переопределения

project/           # Уровень проекта
  input/           # Измененная реализация блока input
  button/
  header/
library-blocks/    # Уровень библиотеки
  input/           # Базовая реализация блока input
  button/
  popup/

Как начать работать с БЭМ

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

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

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

По мере внедрения новых правил возникает потребность в собственных инструментах и технологиях.

БЭМ и технологии

В веб-разработке финальный продукт состоит из разных технологий (например, HTML, CSS, JavaScript). Основной принцип БЭМ-методологии — использовать единые термины и подходы к реализации во всех применяемых технологиях.

БЭМ-дерево

Типичная веб-разработка сводилась к тому, что писался HTML, затем нарезался на шаблоны. При изменении дизайна приходилось менять HTML и шаблоны вручную.

Чтобы избавиться от ручной работы, был добавлен новый уровень абстракции — БЭМ-дерево, которое позволяет работать со структурой веб-страницы в терминах блоков, элементов и модификаторов. БЭМ-дерево — это абстракция над DOM-деревом.

БЭМ-дерево описывает все БЭМ-сущности, которые используются на странице, их состояния, порядок, вложенность. Оно может быть выражено любым форматом, который поддерживает древовидную структуру, например, XML или JSON.

Пример DOM-дерева

<header class="header">
    <img class="logo">
    <form class="search-form">
        <input type="input">
        <button type="button"></button>
    </form>
    <div class="lang-switcher"></div>
</header>

Ему соответствует такое БЭМ-дерево:

header
    logo
    search-form
        input
        button
    lang-switcher

Его можно сравнить с шаблонизатором Jade, но отличие в том, что пишется не HTML, а используется абстракции.

И в заключение

БЭМ-методология — это набор правил и рекомендаций по организации работы над проектом.

В какой-то момент Яндекс отделили методологию от ее практической реализации — платформы.

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

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

Контрольные вопросы

  1. В чем отличие блока от элемента?
  2. Когда следует разделять стиль блока на два и более?
  3. Почему не стоит создавать элементы элементов (block__elem1__elem2)?
  4. В каких случаях следует создавать вспомогательные блоки?
  5. Зачем внешнюю геометрию и позиционирование задавать через родительский блок?
  6. Где следует изменять внешний вид блока?
  7. Где следует изменять позиционирование блока?
  8. Зачем создавать отдельные директории и файлы для каждого блока и технологии?
  9. Когда создавать блок, когда элемент?
  10. Наследуют ли элементы блока его CSS-свойства?
  11. Когда создавать булевый модификатор, когда — модификатор «ключ-значение»?
  12. Когда создавать модификатор, когда — микс?
  13. Почему нельзя писать имя модификатора блока в имени элемента (block_mod__elem)?
  14. Какая вложенность блоков допустима?
  15. Как выбрать имя модификатора?