Дело помаленьку двигается. Хочется, конечно, нарастить темп, но отдых тоже нужен :)
Сегодня сделал разметку по BEM и подумал над поведением блоков при масштабировании (про масштабирование я напишу вместе с началом стилизации в следующем посте, а то уже длиннопост вышел).
Я знаю, среди моих читателей есть люди, которые так же, как и я, изучают верстку и в частности BEM. Так вот, специально для вас я сделал и разобрал разметку <header'а с комментариями, как я обозначал блоки и элементы. Для наглядности, так сказать.
На всякий случай ссылочки по BEM (информация вполне может оказаться для кого-то из вас новой!).
А, да. Не претендую, что прав абсолютно во всех утверждениях и что мое решение идеально - вполне может быть, более опытные разработчики найдут ошибки или видят иной путь реализации, лучший, чем мой. Однако, все дальнейшие рассуждения по максимуму (по крайней мере, я старался :) ) аргументированы, и их логика может помочь вам правильно размечать блоки по BEM. Лучше всего одновременно читать и смотреть на разметку с макетом, чтобы было всё наглядно.
- С header всё понятно - естественно, это блок. Название класса header само собой напрашивается (как самое простое, да и как вообще можно назвать класс хедера?)
- В хедере две секции. Они могут перемещаться внутри хедера относительно друг друга, вполне самостоятельны с точки зрения контента и не влияют друг на друга с точки зрения позиционирования (мы можем разместить контакты под мэйном и смысл хедера от этого не изменится!) - поэтому их нужно именовать как два вложенных (относительно хедера) блока. Их собственные названия, вообще говоря, contacts & main-menu & socials & search-form. ВОПРОС: могут ли данные блоки встречаться сами по себе за пределами хедера где-то ещё? Ответ на него - да (кстати, в футере есть список контактов и соцсетей тоже!), и ещё - я даже могу вынести данные блоки за пределы хедера, если, например, хочу, чтобы они менялись на других страницах. Посему, их лучше назвать не как класс с привязкой к хедеру (header-contacts, например), а как блок с модификатором, указывающим, что они принадлежат хедеру: contacts_header & main-menu_header. Заметьте, здесь и далее я использую соглашение по именованию CamelCase.
- Рассмотрим секцию contacts_header. В ней четыре вложенных компонента: заголовок (имеющий чисто функциональную роль, в соответствиями с правилами семантичной разметки), список, в котором размещены реквизиты компании-оунера, список групп компании в соцсетях и форма поиска. Так вот. Заголовок, с одной стороны, должен иметь функциональный класс, который будет его скрывать. В моей верстке для этого я использую класс visually-hidden (просто как удобный класс с запоминающимся названием). С другой стороны, данный заголовок является неотъемлемой частью секции (так как согласно текущему HTML 5.1 и готовящемуся к продакшену HTML 5.2 семантические блочные элементы сеток, такие как article и section, не валидны без заголовков), заголовок зависим от своей секции по контенту (и позиционированию - в самом хедере это не видно, но вообще по макету это так), и несмотря на то, что внутри секции h2 можно перемещать (флексом), это элемент. Поэтому, согласно BEM, нужно ему дать второй класс contacts__title_header (всё верно, сперва имя блока - потом __имя элемента - потом _имя модификатора (мой модификатор указывает на секцию, а не на своё имя, посему тут значение не нужно). Обратите внимание: я собираюсь скрывать данный заголовок с помощью visually-hidden, поэтому, по идее, мне не нужны для него какие-то другие стили кроме стилей visually-hidden (которые его скрывают). Однако, если предположить, что (при внесении неких правок) я данный заголовок всё же отображаю - у меня уже будет класс (block__title_modifier), с помощью стилей которого возможно быстро внести данные правки. Таким образом, у меня получился микс: с одной стороны, заголовок есть элемент своей секции, с другой стороны - это функциональный блок, который мы скрываем. По макету: видимые заголовки также отличаются видом в зависимости от секции - в них также, нужно будет указывать структуру block__title_modifier для стилизации. Причем block__title можно использовать только для задания формата текста и его дефолтного цвета, а с помощью _modifier мы легко переопределим какой-то из этих параметров (точно понадобится менять цвет). Если сделать разметку и стили таким способом, то фактически стили всех заголовков уже будут - нужно будет просто вешать или удалять класс visually-hidden для их скрытия или показа (тогда как при обычном подходе пришлось бы делать новые стили при каждой такой правке).
- Что касается списка контактов оунера. Список - это блок, поскольку функционально независим, его можно тягать туда-сюда по секции, он встречается в макете ещё раз (в футере). У него есть собственное имя info, но его вид определяется тем, в какой секции он размещен (например, он флекс-контейнер в хидере - а в футере это список). В футере он выглядит по-другому, чем в хедере. Поэтому, необходимо дать ему модификатор, который будет указывать, в какой секции он размещен (например, info_header указывает, что это стиль для блока info в хедере, info_footer - для футера).
- Разберемся с элементами списка и ссылками в info. Элементы списка не могут быть отдельными элементами от самого списка - это элементы с именованием info__item. Однако, они могут по-разному себя вести (с точки зрения позиционирования) в разных реализациях info для хедера и футера. Посему, необходимо дать им тот же модификатор _header (и _footer), что есть у нас для заголовков.
- Внутри li находятся ссылки с текстом реквизитов. Это не те ссылки, по которым мы переходим на другие страницы. Задумка такова: я нажимаю на телефон - открывается некое средство (viber, допустим), с которого можно позвонить оунеру (или просто появляется запрос "хотите позвонить?"), жмём на мэйл - открывается почтовый ящик, с которого можно послать на тот адрес мэйл, и т.д. Реализация данных механизмов - прерогатива не верстальщика. Однако, ссылки в себе будут содержать стили, определяющие их вид на странице. Опять же, понятно, нам понадобится определять, где находится ссылка, поэтому опять понадобятся модификаторы _header и _footer. Поскольку список ссылок - семантичная обертка для блока info со ссылками внутри (если бы я "на дивАх" верстал, так бы и было!), ссылки эти нельзя использовать вне info - а значит, они - элементы info__link, вложенные в info__item (так делать можно и нужно, когда нет необходимости в создании служебных блоков).
- Абсолютно аналогична ситуация и со списком соцсетей socials. Этот список - тоже по тем же причинам блок, его li - элементы с __item, его ссылки - тоже его элементы __link, вложенные в __item. И тоже там понадобятся модификаторы _header (сюда) и _footer (в футер), чтобы внести разницу в стилях для блока (заметьте, что для реализации данного блока в футере - секция Follow Us - различается в макете для хедера и футера гораздо сильнее, чем список контактов).
- Форма поиска. Да, это именно форма, а не просто поле ввода. Сама форма с точки зрения BEM - блок с именем search-form. В отличие от списков, он уникален для страницы, поэтому его можно рассматривать как вложенный блок для хедера. Поэтому, его можно именовать как header-search-form (header указывает на то, что форма в хедере и только в нём, search придаёт форме смысл - так коллега из, допустим, Уганды легко догадается по коду, что это стиль именно для формы поиска!).
- Label необходим в данной форме для того, чтобы сохранить структуру формы с точки зрения её доступности (для машин и для "читалок"), поэтому мы должны его скрыть (visually-hidden мне в помощь :) ). Также, label связан с полем поиска - следовательно, влияет на иные компоненты внутри блока и не используется отдельно от них - посему, это точно элемент с именем header-search-form__search-label. Здесь не нужны модификаторы. В итоге - получился микс, поскольку мы использовали лейбл и как функциональный блок (отображающий текст для машин и читалок), и как элемент формы поиска.
- Инпут в ней актуален только для данной формы, и без него форма не имеет никакого смысла (поскольку некуда будет вводить запрос на поиск). Значит, этот input - элемент c именем header-search-form__search-input. Все стили для него вполне возможно написать прямо в нём, и не будут меняться в зависимости от того, в какой части макета он находится. Значит, модификаторы здесь не нужны.
- Секция main-menu. Тут в целом всё просто и аналогично. h2 у нас тут выполняет ту же функцию, что и в пункте 3 - у него та же реализация. nav, точно так же, как было описано в пп. 4-7, является блоком, содержащим список ссылок (его вложенный блок!), у которого есть элементы списка и элементы-ссылки. А вот с logo (который, бесспорно, является блоком!) ситуация интереснее.
- Давайте посмотрим, какова структура блока logo. В нём есть три составных компонента: картинка, главная надпись (TripFInder) и вспомогательная надпись. Причём картинка, учитывая то, что в макете это иконочный символ FontAwesome, (для джумлы! :) ), реализуется в качестве псевдоэлемента (вопрос для какого элемента - но это уже проблема стилизации). Учитывая то, что логотип является единым целым, все вложенные в logo компоненты влияют друг на друга и не используются нигде отдельно. Значит, это всё элементы. Учитывая то, что логотип единообразен (и, кстати, для данного макета вообще уникален на странице), нужно понимать, что модификаторы здесь не нужны - всю стилизацию можно выполнить с помощью стилей самих элементов. Кстати, есть вариант обернуть логотип в ссылку - но учитывая специфику макета, тут не на что переключаться, и логотип, который вообще по нажатию ведет на главную страницу, можно оставить так.
По абсолютно тем же принципам сделана и вся остальная разметка. Мне нравится то, что получилось. В целом, могу сказать, что методология неплоха как минимум потому, что делает именования единообразными, а код - более читабельным. Хотя, недостаток - необходимо время на то, чтобы создать в своей разметке классы по BEM (уменьшается с опытом и у разработчиков есть инструмент автоматизации - я только в первый раз для понимания всё ручками делал). Плюс, классы получились "развесистыми" по количеству символов - конечно, это компенсируется отсутствием сложных селекторов в стилях, но тем не менее. Может, это именно у меня так получилось, или всё зависит от структуры макета :) В общем, первый опыт использования BEM явно был полезен и интересен.
P.S. В BEM существует своя файловая структура и сборщики, которые пока для меня тёмный лес. Сейчас я не стану их трогать и ограничусь только разметкой и стилями по BEM. Я начинал делать раньше ещё один макет - называется Agnecy (не опечатка, видимо его так назвали чтобы отличать от других) - возможно, там как раз и применю BEM полностью, как его рекомендуется применять.
P.P.S https://echo.htmlacademy.ru - указывая его в форме в атрибуте method, можно тестить, какие данные и в каком виде отправляются с вашей формы на сервер. То есть, это самый простейший и бесплатный эмулятор сервера, который покажет, если вы хотите затестить форму, те данные, которые пересылаются с неё, без необходимости работы с самим сервером и его настройки. С его помощью хорошо ловить баги обработки данных в форме, особенно если вы где-то что-то меняли в логике обработки, вычисляете отправляемые значения или пользуетесь скрытыми полями. Вполне удобно :)