Html — Посмотрите html разметку по методологии BEM


Содержание

Простые правила разметки

Как писать классы по БЭМ?

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

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

Подробнее можно почитать в разделах Быстрый старт и Часто задаваемые вопросы на сайте bem.info.

Ниже показаны примеры кода.

Простой пример: Блок + Элемент #

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

Добавляем класс содержащий назначение элемента: .popup :

Теперь попробуем добавить классы вложенным элементам:

Классы удобные, но не уникальные. Если на странице будут ещё элементы с классами .title и .text , их стили могут затронуть элементы в попапе. Селектор типа .popup .title может в будущем создать проблемы со специфичностью. Можно придумать другие классы, но чем больше похожих по смыслу элементов, тем сложнее придумывать новые классы.

А теперь применим БЭМ-нотацию: каждому элементу внутри блока добавим префикс с классом родителя, например, для заголовка это будет popup__title :

Теперь эти классы легко решают сразу две задачи: во-первых, благодаря уникальным классам стили для них никогда не пересекутся с другими подобными элементами на странице, а во-вторых, по таким классам сразу видно, что это элементы блока .popup .

Пример посложнее: Блок + Элемент + Модификатор #

Для примера возьмём сервисное сообщение на сайте. Обычно такие сообщения бывают разных видов, например, сообщение об успешном завершении действия или об ошибке.

Логично использовать одну и ту же разметку, но с разными цветовыми темами. Именно здесь очень пригодятся модификаторы.

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

Оба сообщения будут иметь рамку толщиной один пиксель, но для сообщения об успешной операции она будет зелёной, а для сообщения об ошибке — красной.

Ещё сложнее: что делать, если хочется сделать элемент элемента? #

Например, на странице есть блок новостей:

Заголовок блока логично получает класс .news__title , список — .news__list , а отдельная новость — .news__item :

Тут никаких проблем возникнуть не должно. Теперь добавим разметку отдельной новости:

Нам нужно добавить класс заголовку новости. Первым делом приходит в голову .news__title , но такой класс уже занят. Предположим, что второй элемент будет не .title , а .subject , тогда в CSS получается такое:

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

Следующий вариант — .news__item__title , но в БЭМ нельзя создавать элемент элемента, и это понятно, потому что получается каша. Ещё вариант: .news__item-title — тоже не годится, потому что может быть неочевидным как title соотносится с item . Как же быть?

Решение простое: на уровне элемента .news__item можно объявить новый блок (например, .news-item ), и строить вложенные классы уже от него. Да, это не самостоятельный переиспользуемый блок, здесь объявление блока нужно только для того, чтобы разгрузить селекторы. Что получается:

Проблема решена: нам больше не нужно использовать монструозные классы, при этом класс точно описывает элемент, и в CSS будет сразу понятно какой класс за что отвечает:

Простой и удобный выход из неудобной ситуации.

Больше примеров разметки можно увидеть здесь.

Ещё одно хорошее руководство по использованию БЭМ есть здесь.

Вёрстка графических компонентов

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

При создании графических компонентов («виджетов») в первую очередь придумывается их HTML/CSS-структура.

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

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

Семантическая вёрстка

HTML-разметка и названия CSS-классов должны отражать не оформление, а смысл.

Например, сообщение об ошибке можно сверстать так:

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

При семантической вёрстке классы описывают смысл («что это?» – меню, кнопка…) и состояние (открыто, закрыто, отключено…) компонента.

У предупреждения будет класс warning и так далее, по смыслу.

Семантическая вёрстка упрощает поддержку и развитие CSS, упрощает взаимодействие между членами команды.

Такая вёрстка удобна для организации JS-кода. В коде мы просто ставим нужный класс, остальное делает CSS.

Состояние виджета – класс на элементе

Зачастую компонент может иметь несколько состояний. Например, меню может быть открыто или закрыто.

Состояние должно добавляться CSS-классом не на тот элемент, который нужно скрыть/показать/…, а на тот, к которому оно «по смыслу» относится, обычно – на корневой элемент.

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

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

Или, к примеру, разметка для индикатора загрузки может выглядеть так:

Состояние индикатора может быть «в процессе» (loading) или «загрузка завершена» (complete). С точки зрения оформления оно может влиять только на показ внутреннего span , но ставить его нужно всё равно на внешний элемент, ведь это – состояние всего компонента.

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

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

Префиксы компонента у классов

Рассмотрим пример вёрстки «диалогового окна»:

Диалоговое окно может иметь любое HTML-содержимое.

А что будет, если в этом содержимом окажется меню – да-да, то самое, которое рассмотрели выше, со ?

Правило .dialog .title применяется ко всем .title внутри .dialog , а значит – и к нашему меню тоже. Будет конфликт стилей с непредсказуемыми последствиями.

Конечно, можно попытаться бороться с этим. Например, жёстко задать вложенность – использовать класс .dialog > .title . Это сработает в данном конкретном примере, но как быть в тех местах, где между .dialog и .title есть другие элементы? Длинные цепочки вида .dialog > . > .title страшновато выглядят и делают вёрстку ужасно негибкой. К счастью, есть альтернативный путь.

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

Здесь имя dialog , так что все, относящиеся к диалогу, будем начинать с dialog__

Здесь двойное подчёркивание __ служит «стандартным» разделителем. Можно выбрать и другой разделитель, но при этом стоит иметь в виду, что иногда имя класса может состоять из нескольких слов. Например title-picture . С двойным подчёркиванием: dialog__title-picture , очень наглядно видно где что.

Есть ещё одно полезное правило, которое заключается в том, что стили должны вешаться на класс, а не на тег. То есть, не h2 < . >, а .dialog__title < . >, где .dialog__title – класс на соответствующем заголовке.

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

На практике из этих правил зачастую делают исключения. Можно «вешать» стили на теги и использовать CSS-каскады без префиксов, если мы при этом твёрдо понимаем, что конфликты заведомо исключены.

Например, когда мы точно знаем, что никакого произвольного HTML внутри элемента (или внутри данного поддерева DOM) не будет.

Описанное выше правило именования элементов является частью более общей концепции «БЭМ», которая разработана в Яндексе.

БЭМ предлагает способ организации HTML/CSS/JS в виде независимых «блоков» – компонентов, которые можно легко перемещать по файловой системе и между проектами.

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

Более подробное описание основ БЭМ можно почитать в статье https://ru.bem.info/articles/bem-for-small-projects/, а о системе вообще – на сайте http://ru.bem.info.

Итого

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

Класс, описывающий состояние всего компонента, нужно ставить на его корневом элементе, а не на том, который нужно «украсить» в этом состоянии. Если состояние относится не ко всему компоненту, а к его части – то на соответствующем «по смыслу» DOM-узле.

Классы внутри компонента должны начинаться с префикса – имени компонента.

Это не всегда строго необходимо, но позволяет избежать проблем в случаях, когда компонент может содержать произвольный DOM, как например диалоговое окно с произвольным HTML-текстом.

Использование .dialog__title вместо .dialog .title гарантирует, что CSS не применится по ошибке к какому-нибудь другому .title внутри диалога.

Задачи

Семантическое меню

Посмотрите на вёрстку горизонтального меню.

Что делает эту вёрстку несемантичной? Найдите 3 ошибки (или больше).

Как бы вы сверстали меню правильно?

Несмотря на то, что меню более-менее прилично отображается, эта вёрстка совершенно не семантична.

Во-первых, меню представляет собой список элементов, а для списка существует тег LI .

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

и т.п.

Во-вторых, класс rounded-horizontal-blocks показывает, что содержимое должно быть оформлено как скруглённые горизонтальные блоки. Любой класс, отражающий оформление, несемантичен.

Правильно – чтобы класс был смысловым. Например,

    будет говорить о том, что смысл элемента – «меню».

В-третьих, элемент .vertical-splitter . Здесь класс вполне семантичен, этот элемент списка является вертикальным разделителем, так что здесь всё в порядке. Но на этот раз несемантичность – в содержимом.

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

Поэтому от него следует либо вообще избавиться, либо переместить в CSS при помощи ::before .

И, наконец, это не обязательно и не ошибка, но обычно элементы, которые являются ссылками или кнопками, оформляют в или .

Вариант ниже – семантичен:

Дополнительно, классы помечены префиксом компонента, на тот случай, если в заголовках появится произвольный HTML.

Меньше классов в html-разметке с BEM

0 Gregor Oi [2020-08-09 09:12:00]

Я пытаюсь вытащить все классы цепочки из моей html-разметки. Потому что тогда у меня есть все мои стили в моем файле css, и я не заглядываю в свой html, чтобы увидеть, как некоторые элементы были стилизованы, а разметка выглядит намного чище.

. и внутри моего css, у меня это есть.

Это хороший подход?

И если у меня есть блок с другим блоком, я думаю, что есть два способа

B) Я удаляю класс.

. и добавьте его в мой css.

Что вы думаете, что лучше? A) показывает мне лучше, когда начинается форма модуля, но имеет больше классов и порядок важен. B) следует больше способов для более чистой разметки, но не показывает мне форму выпуска> form__row.

Зачем нужен БЭМ

Следуете ли вы БЭМу, и насколько он востребован вне Яндекса? — спрашивает наша ученица Евгения. Следуем, Евгения, и БЭМ вполне применим не только в Яндексе. Давайте разберёмся.

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

Круто, да? Но зачем вам масштабируемость и командная работа, если вы один верстальщик на проекте, который не претендует на популярность Яндекса? Чтобы ответить на этот вопрос, нужно отмотать историю лет на 10 назад, когда это подход только начали формулировать.

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

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

Потом появились абсолютно независимые блоки (АНБ), где у элементов внутри есть свой префикс с именем родителя, а состояния блоков снова дублируют класс, но уже с постфиксом. Подход обрёл черты современного БЭМа, одна из которых — многословность классов.

Эта многословность гарантирует уникальность элементов и модификаторов в рамках одного проекта. За уникальностью имён блоков вы следите сами, но это довольно просто, если каждый блок описан в отдельном файле. Глядя на такой класс в HTML или CSS, можно легко сказать, что это, и к чему оно относится.

Изначально АНБ, а потом и БЭМ, решали задачу важную для вёрстки любых масштабов: предсказуемое поведение и создание надёжного конструктора. Вы же хотите, чтобы ваша вёрстка была предсказуемой? Вот и Яндекс тоже. Ещё это называется «модульность» — о ней хорошо написал Филип Уолтон в «Архитектуре CSS», ссылка на перевод в описании.


Через пару лет в Яндексе окончательно сформулировали нотацию БЭМ. Любой интерфейс предлагалось разделять на блоки. Неотделимые части блоков — элементы. У тех и других есть модификаторы.

Например, блок поиска по сайту. Он может быть в шапке и в подвале — значит это блок. В нём есть обязательные части: поле поиска и кнопка «найти» — это его элементы. Если поле нужно растянуть на всю ширину, но только в шапке, то блоку или элементу, который отвечает за это растягивание, даётся модификатор.

Для полной независимости блоков мало назвать классы правильно или изолировать стили, нужно собрать всё, что к нему относится. В проекте по БЭМу нет общего script.js или папки images со всеми картинками сайта. В одной папке с каждым блоком лежит всё, что нужно для его работы. Это позволяет удобно добавлять, удалять и переносить блоки между проектами. Потом конечно все ресурсы блоков при сборке объединяются в зависимости от задач проекта.

Цукерберг рекомендует:  Php - Реально ли сделать форму регистрации в WP со своими полями

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

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

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

Возьмём, к примеру, русский язык. Мы же пишем с прописной имена людей, названия и прочее такое? Пишем. Чтобы легко потом считывалось: это Надя или надежда на лучшее? Уж не говоря про знаки препинания и другие полезные договорённости. Вот буква ё, например смягчает… так, о чём мы? Да, БЭМ.

До БЭМа были проекты с портянками стилей, которые нельзя трогать. Они копились годами, слой за слоем, как обои в древней коммуналке. Их просто подключали первыми, а потом перезаписывали что мешало. Когда у вас есть div < font-size: 80% >— это даже уже не смешно.

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

Были и другие методологии: OOCSS Николь Салливан, SMACSS Джонатана Снука, вариации БЭМа и целые фреймворки. Даже у нас на продвинутом интенсиве HTML Академии можно было выбрать любую методологию для вёрстки учебного проекта.

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

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

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

Введение в методологию БЭМ

Давайте посмотрим правде глаза, мы все хотели бы сделать наш код более понятным для чтения. Это помогло бы нам работать быстрее и продуктивнее и, когда другие работают с нами, мы можем сохранять ясность и последовательную семантику. Сегодня так много стандартов и терминов в мире CSS: OOCSS, SMACSS, БЭМ и другие! Все эти подходы служат для улучшения структуры CSS кода и сегодня мы поговорим о БЭМ.

БЭМ означает Блок Элемент Модификатор. Он предполагает структурированный способ именования классов на основе свойств конкретного элемента. Если Вы когда-нибудь встречали класс с названием вроде header__form—email — это и есть БЭМ. Имейте ввиду, что в методологии БЭМ, мы будем использовать только названия классов (не ID). Названия классов позволяют повторять названия БЭМ, если это необходимо, и создавать более последовательную структуру кода (как в HTML, так и в CSS/Sass файлах). Давайте разберем это более подробно.

Блок — это независимый контейнер или контекст на странице. Думайте о нем как о большом структурном куске кода. На Вашей странице скорее всего будут header, footer, sidebar и основное содержание страницы. Каждый из этих элементов может быть независимым блоком. Взгляните на изображение ниже:

Блок элемент образует корневое название класса, которое всегда идет первым. Просто запомните, что как только Вы определились с блоком, можете начинать называть остальные элементы.

Элемент

Элемент является частью блока. Блок — это родительский контейнер, а элементы — его составляющие.

Я знаю, это выглядит немного странно, но как только Вы начнете это использовать, сами не поверите, как раньше писали CSS код без БЭМ! Двойное подчеркивание помогает быстро визуально перемещаться и манипулировать кодом.

Вот несколько примеров того, как работает методология элементов:

Как Вы можете заметить, здесь много места для творчества, что дает возможность настроить методологию под себя. «Navigation» можно изменить на «nav», «tagline» можно изменить на «tag» или «tagLine». Главное делать названия классов простыми, понятными и точными. Однако не переусердствуйте, помому что Ваши стили и html должны оставаться «сухими» (не повторяйтесь). Не должно быть проблемой обновить названия классов, если нашли более подходящие (просто постарайтесь придерживаться их! ). Элементы будут составлять ядро названий Ваших классов, помогая понять, как лучше структурировать стили, и, как управлять макетом.

Модификаторы

И вот сейчас начнется самое интересное (если оно не началось до этого!). Когда Вы выбираете название класса, стремитесь сделать этот элемент повторяемым, чтобы Вам не пришлось писать новые названия классов в других разделах сайта, если стили элементов одинаковы. Если необходимо модифицировать (изменить) стили конкретного элемента, можете использовать модификатор (конечно же!). Чтобы сделать это, добавьте двойной дефиз — после элемента (или блока). Вот краткий пример

Однако будьте осторожны с этим! Помните, чтобы делать названия классов простыми и не повторяться или создавать дополнительные ненужные классы. Давайте поговорим об этом используя код, возьмем header страницы в качестве блок элемента.

Если Вы используете вторичную навигацию, есть вероятность, что расположение и расстояние в навигации одинаковое, но вторичная имеет другой цвет. Вы можете либо продублировать оригинальные стили, либо, даже лучше, использовать препроцессор. Например в Sass с помощью директивы @extend можно унаследовать свойства главного элемента (так, чтобы дочерний элемент перенял все свойства) и затем изменить необходимые стили.

Вы возможно думаете «но ведь название класса такое длинное!». То, как я это вижу: названия классов БЭМ очень точные, понятные, просты для чтения внутри html и четко дают понять, для чего служат.

Что мне также нравится в БЭМ — это возможность использовать только одно название класса для каждого html тэга. Давайте посмотрим, как это работает для label. Стандартные селекторы:

против селекторов БЭМ:

Языки вроде Sass (Sass в особенности) помогают быстро иметь элементы с одними и теми же стилями с небольшими изменениями. В примере ниже не допускается дублирование стилей, но мы можем изменить только то, что нам нужно. Но больше всего мне нравится в БЭМ то, что мне не нужно объединять двусмысленные классы вроде » panel panel-default col-md-3 «. Если Вы используете фреймворк вроде Foundation, Вы можете начать использовать миксины. Но для простого примера, давайте стилизуем те label, которые мы только что обозначили.

Заключение

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

Из моего личного опыта, БЭМ помог мне строить прототипы более эффективно и вывел на новый уровень написания кода!

Дополнительные материалы

А что Вы думаете о БЭМ, есть ли у Вас какие-нибудь советы, рекомендации или трюки для читателей Tuts+? Пишите в комментариях!

БЭМ-методология организации CSS-кода

Писать CSS-код легко. Масшабировать и поддерживать его — нет

Это правда. И это неоднократно подтверждалось во многих проектах. Будь то конструктор сайтов с настраиваемыми темами (проект Getsocio — 28 тысяч строк CSS) кода или сайт-визитка со сравнительно небольшим количеством стилей. Любые сколь-нибудь сложные правки в связи с изменениями дизайна или с появлением новых страниц приводят к долгому рефакторингу, в самом запущенном случае — к дублированию стилей. При этом постоянно присутствует риск что-нибудь сломать в самом неожиданном месте.

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

Почему так происходит? На начальном этапе, когда разработчики получают макеты, они создают структурy ассетов, в которую довольно хорошо вписывается весь существующий дизайн. Проблема рождается именно в этот момент, потому что текущий дизайн — это вершина айсберга по сравнению с будущим дизайном. Можно представить варианты решений, приходящих в голову на данном этапе. У нас всего две страницы — можно поместить все стили в один файл. Или еще. У нас десять страниц и все они непохожи, поэтому не стоит заморачиваться выделением компонент внутри страниц и вынесением их в отдельные файлы, проще создать по файлу стилей на каждую страницу. Идеи выглядят вполне здравыми, учитывая текущие аспекты дизайна. Опытные разработчики даже могут сделать некоторые предположения о том, как поменяется дизайн в ближайшем будущем, но немногие готовы к тому, во что превратится проект через, скажем, пять лет.

CSS имеет ряд недостатков, которые приводят к вышеперечисленным проблемам. В недавнем докладе (React: CSS in JS), породившем множество дискуссий в среде фронтенд разработчиков, один из сотрудников Facebook озвучил проблемы с масштабированием CSS. Среди них использование глобального пространства имен, удаление мертвого кода, изоляция и т. д. В итоге он предложил хранить стили в JavaScript. Интересное, но довольно радикальное решение, не всегда применимое к обычным сайтам, страницы которых рендерятся на сервере. Многие компании, не только Facebook, пытаются решить проблему масштабирования CSS. Поэтому на сегодняшний день существует множество подходов к написанию стилей. Одна из наиболее интересных методологий родилась в Yandex.

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

Пройдемся немного по понятиям. Блок — независимый компонент страницы, который инкапсулирует внутри себя поведение (JavaScript) и внешний вид (CSS). Благодаря независимости блока возможно его повторное использование в любом месте страницы. Элемент — составная часть блока, которая не может использоваться в отрыве от него. Модификатор — сущность, изменяющая внешний вид блока или элемента в зависимости от состояния или требований дизайна. При желании можно использовать несколько блоков на одном HTML элементе. Такой способ в терминологии БЭМ имеет название Микс.

Теперь можно вернуться к нашим проблемам и посмотреть какое решение нам предлагает БЭМ. Первая проблема — это глобальное пространство имен. Пусть у нас есть навигационное меню.

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

В этом примере проблема решается выделением двух компонент. toolbar и user-profile — имена этих компонент в глобальном пространстве имен. Дальше мы определяем стили внутренних элементов в пределах этих компонент.

Но такое решение очень плохо масштабируется. Если представить себе более сложные компоненты ( page , company-preview , user-post ), то мы получим ту же самую проблему, но уже в пределах одного компонента. Уточнение селекторов, например .page > .edit — очень плохая идея, так как создает связанность между HTML шаблонами и представлением. Меняя шаблон, нам нужно будет поменять и стили тоже. Вдобавок ко всему добавляя класс к селектору мы меняем его специфичность, а это в свою очередь усложняет переопределение CSS правил для элемента. В других местах появляются классы для увеличения специфичности, начинается гонка селекторов и головная боль для верстальщика.

БЭМ предлагает отказаться от каскадности, тем самым однозначно определяя элемент.

Вложенные элементы, принадлежащие блоку, будут использовать это имя блока toolbar в качестве префикса. __ служит разделителем между блоком и элементом, а _ — разделителем между БЭМ-сущностью (в данном случае элементом) и модификатором. Здесь toolbar__item_edit и toolbar__item_edit — это модификаторы элемента toolbar__item .

Незаметно для себя мы одним махом решили целый ряд проблем. Элементы теперь инкапсулированы внутри блоков и изолированы от других элементов. Для описания стилей блока и его элементов можно выделить отдельный файл или даже каталог на файловой системе. Таким образом, только лишь взглянув на структуру проекта, можно сказать что находится в глобальном пространстве. Становится легче отслеживать иерархические связи в пределах блока. CSS код становится самодокументируемым. Упрощается поиск селекторов по проекту, а также модификация стилей и удаление неиспользуемого кода.

Осталось поговорить о самодисциплине. Чтобы не свести на нет полученные приимущества нужно следовать некоторым правилам и рекоммендациям. Можно держать в голове следующий чеклист.

  • Позиционирование блока задается родителем
  • Для описания сущностей используются классы, но не id
  • Нельзя создавать элементы элементов ( block__elem1__elem2 )
  • В именах модификаторов и элементов всегда присутствует имя блока
  • Из предыдущего пункта следует, что нельзя создавать глобальные модификаторы
  • Блоки могут не содержать вложенных элементов ( link )
  • Блоки могут заключать в себе все содержимое страницы или крупные ее части ( page , page-section )

Чтобы не утратить возможность переносимости блока между разными частями страницы желательно чтобы позиционирование и размеры блока ( margin , top , left , width ) задавались родителем.

Предположим что наш toolbar находится внутри блока header и должен занимать его правую половину. Решение может выглядеть следующим образом.

CSS код блока toolbar при этом остается неизменным.

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

Разберем еще один пример. Предположим к нам пришел такой дизайн тулбара.

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

Здесь для того чтобы не дублировать общие стили для каждого элемента блока toolbar мы выделяем элемент toolbar__item и используем микс с остальными элементами: toolbar__button , toolbar__spacer и toolbar__text . Некоторые элементы являются вложенными, но при этом внутренняя структура блока все еще остается плоской, то есть не нарушается правило о том, что нельзя создавать элементы элеметов. И еще одно — все элементы, требующие стилизации имеют классы, в том числе и img . Ссылка на реализацию со стилями.

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

БЭМ для начинающих. Очевидные и неочевидные вопросы верстки

Эта статья написана по мотивам БЭМапа — митапа по БЭМ — с одноименным названием БЭМ для начинающих.

Нас часто спрашивают о верстке по БЭМ и про технологии, которые мы используем: почему нужно делать так, а не иначе? Зачем мы создали целый стек новых технологий, когда можно пользоваться готовыми? Зачем придумали такие длинные имена в классах?

Цукерберг рекомендует:  Люди - Ищу Data Scientist

На БЭМапе Владимир Гриненко дал ответы на эти вопросы. Мы решили сохранить их в статье.

Немного теории и практики:

  • Основные почему
  • Основы БЭМ
  • Модификаторы и миксы
  • Удобство параллельной разработки и верстка блоками
  • Блоки в файловой структуре
  • Шаблоны в БЭМ
  • Тестирование верстки
  • Сборка проекта
  • С чего начинать?

Зачем вам БЭМ

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

Основные почему

  • Почему не используем >ID определяет уникальное имя HTML-элемента. Если имя уникально, второй раз в интерфейсе его использовать не получится. Это мешает повторно использовать код.

1. ID обязателен для работы с JavaScript.

На практике современным браузерам не важно, с какими данными работать: ID или классами. Браузер одинаково быстро обрабатывает любой селектор.

Если поместить в контрол, > Текст можно написать так: Текст .

Не используем селекторы тега

HTML-разметка страниц нестабильна: новый дизайн сайта может поменять вложенность разделов, уровень заголовоков (например, с

) или превратить абзац

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

Расширенный набор семантических тегов также не может выразить все потребности верстки.

Например: в шапке страницы расположен логотип, по клику на который открывается главная страница сайта ( index ).

Напишем разметку с помощью тегов: для картинки используем тег , для ссылки — тег .

Чтобы отличать ссылку с логотипа от обычной ссылки в тексте, понадобятся дополнительные стили. Отменим подчеркивание и синий цвет для ссылки в логотипе:

На главной странице ссылка в логотипе не нужна, поэтому изменим разметку для index -страницы:

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

На первый взгляд, такой код имеет право на существование. Но представьте ситуацию, в которой дизайнер убирает логотип из макета. Такие имена селекторов не помогут понять, какие стили удалять из проекта вместе с логотипом. Селектор header a не показывает связь ссылки и логотипа. Такой селектор может принадлежать ссылке в меню шапки или, например, ссылке на профиль автора, а селектор header span может относиться вообще к любой части шапки.

Чтобы избежать путаницы, достаточно записать стили для логотипа с помощью селектора класса с именем logo :

Не используем общий сброс стилей (reset)

Общий сброс стилей — это глобальные CSS-правила, созданные для всей страницы. Они оказывают влияние на все узлы верстки, нарушают независимость компонентов и затрудняют их повторное использование.

В БЭМ не принято использовать «reset» и «normalize» даже для отдельно взятого блока.

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

Не используем универсальный селектор (*)

Универсальный селектор сообщает, что в проекте создан стиль, который влияет на все узлы в верстке. Это накладывает ограничения на повторное использование верстки в другом проекте:

  • Необходимо дополнительно переносить в проект стили под «звездочкой». Но в таком случае универсальный селектор может повлиять на стили в новом проекте.
  • Необходимо добавлять стили со «звездочкой» в переносимую верстку.

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

Общие стили не выигрывают время: часто разработчик начинает с того, что сбрасывает все отступы для универсальных компонентов ( * < margin: 0; padding: 0; >), а потом все равно задает их как в макете (например, margin: 12px; padding: 30px; ).

Не используем вложенные селекторы

Вложенные селекторы увеличивают связность кода и затрудняют его повторное использование.

БЭМ не запрещает вложенные селекторы, но рекомендует не злоупотреблять ими.

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

Не используем комбинированные селекторы

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

Рассмотрим такой код:

Зададим CSS-правила в селекторе .button.button_theme_islands ради экономии в записи.

Теперь добавим блоку модификатор active :

Селектор .button_active не переопределит свойства блока, записанные как .button.button_theme_islands , так как специфичность .button.button_theme_islands выше, чем у .button_active . Для успешного переопределения селектор модификатора блока также должен быть скомбинирован с селектором .button и объявлен ниже .button.button_theme_islands , так как специфичность обоих селекторов одинакова:


Если использовать простые селекторы классов, переопределение стилей не вызовет проблем:

Не совмещаем тег и класс в селекторе

Совмещение тега и класса (например, button.button ) повышает специфичность CSS-правил и затрудняет их переопределение.

Рассмотрим такой код:

Зададим CSS-правила в селекторе button.button .

И добавим блоку модификатор active :

Селектор .button_active не переопределит свойства блока, записанные как button.button , так как специфичность button.button выше чем у .button_active . Чтобы повысить специфичность, селектор модификатора блока также нужно скомбинировать с тегом button.button_active .

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

Методология в редких случаях допускает объединение селекторов тега и класса, например, для стилизации комментариев в CMS-системах, которые не позволяют генерировать правильную разметку.

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

Не используем селекторы атрибутов

Селекторы атрибутов по информативности уступают селекторам классов. Чтобы доказать это, рассмотрим пример с формой поиска в шапке:

Воспользуемся селекторами атрибутов, чтобы записать стили для формы:

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

Можно записать, например, так:

Код стал более однозначным: теперь понятно, что стили относятся к форме, которая отвечает за поиск.

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

Короткие выводы

Классы — единственный селектор, который позволяет изолировать стили каждого компонента в проекте, повысить читаемость кода и не ограничивать повторное использование верстки.

БЭМ. От теории к практике

  • Основы БЭМ
  • Модификаторы и миксы
  • Удобство параллельной разработки и верстка блоками
  • Блоки в файловой структуре
  • Шаблоны в БЭМ
  • Тестирование верстки
  • Сборка проекта
  • С чего начать?

Основы БЭМ

Методология БЭМ — это набор универсальных правил, которые можно применять независимо от используемых технологий, будь то CSS, Sass, HTML, JavaScript или React.

БЭМ помогает решить следующие задачи:

  • повторно использовать верстку
  • безболезненно менять верстку местами в одном проекте
  • переносить готовую верстку из проекта в проект
  • создавать стабильный, предсказуемый и понятный код
  • сократить время на отладку проекта

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

Именно блокам и элементам посвящены первые две буквы в аббревиатуре БЭМ.

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

Чтобы показать всю силу БЭМ-нейминга, рассмотрим пример с формой. По БЭМ-методологии форма будет представлена блоком form . В HTML имя блока всегда записывается в атрибуте class :

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

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

Запись имен в классах с помощью блоков и элементов решает еще одну важную проблему: избавляет от вложенности селекторов. У всех селекторов в БЭМ-проекте одинаковый вес. То есть переопределять стили, написанные по БЭМ, гораздо удобнее.

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

Суть именования компонентов в БЭМ в том, что в имени можно явно указать связь блока и его элементов.

Третья буква в аббревиатуре БЭМ

Официально буква «М» означает «модификатор», но негласно под нее попадает еще одно очень важное понятие в БЭМ — «микс». И модификаторы и миксы изменяют блок и его элементы. Давайте рассмотрим подробнее.

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

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

Разберемся, как работают модификаторы.

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

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

В БЭМ можно добавить блоку новые стили с помощью модификатора:

Запись говорит о том, что блоку form присвоен модификатор type со значением original . В классической схеме имя модификатора отделяется от имени блока или элемента одним подчеркиванием.

Форма может быть уникальна по разным показателям — цвету, размеру, типу, теме оформления. Все эти параметры можно задать с помощью модификатора:

Одна и та же форма может выглядеть по-разному и при этом быть одного размера:

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

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

Поэтому модификатор всегда должен находиться на одном DOM-узле с блоком или элементом, к которому он относится.

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

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

Миксом называется одновременное размещение нескольких БЭМ-сущностей (блоков, элементов, модификаторов) на одном DOM-узле.

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

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

Можно вынести общие стили для таких блоков, но повторно использовать такой код не получится.

Рассмотрим, как можно создать семантически разные блоки с помощью микса на примере все той же формы:

В селекторе класса .form описаны все стили, которые могут быть у любой формы (заказов, поиска или регистрации):

Теперь предстоит сделать из универсальной формы форму поиска. Для этого в проекте необходимо создать дополнительный класс search , который отвечает только за поиск. Чтобы объединить стили и поведение класса .form и .search , нужно разместить эти классы на одном DOM-узле:

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

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

Нужная функциональность для ссылок уже реализована в блоке link . Но ссылки в меню должны отличаться визуально от ссылок в тексте. Существует несколько способов изменить ссылки в меню:

1. Создать модификатор для пункта меню, который превратит пункт в ссылку:

В таком случае для реализации модификатора придется скопировать поведение и стили блока link . Это приведет к дублированию кода.

2. Воспользоваться миксом универсального блока link и элемента item блока menu :

Микс двух БЭМ-сущностей позволит применить базовую функциональность ссылок из блока link и дополнительные CSS-правила из блока menu , и не копировать код.

Внешняя геометрия и позиционирование. Отказываемся от абстрактных HTML-оберток

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

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

Рассмотрим на примере универсального блока меню, который нужно разместить в шапке. В верстке блок меню должен отступать от родительского блока на 20px.

Существует несколько решений для этой задачи:

1. Написать стили с отступами самому блоку меню:

В таком случае блок menu перестанет быть универсальным. Если понадобится разместить меню в подвале страницы, придется править стили, потому что отступы скорее всего будут другими.

2. Создать модификатор для блока меню:

В таком случае в проекте появятся два типа меню, хотя это не так. Меню остается одно и то же.

3. Определить внешнее позиционирование блока — вложить блок menu в абстрактную обертку (например, блок wrap ), где задать все отступы:

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

Отступ от родительского блока — это не свойство вложенного блока быть с таким отступом. Это свойство родительского блока — знать, что вложенный в него блок должен отступать от границы на определенное количество пикселей.

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

Продолжим рассматривать пример:

Здесь внешняя геометрия и позиционирование блока menu задана через элемент header__menu . Блок menu не специфицирует никакие отступы и может быть легко использован повторно.

Элемент родительского блока (в нашем случае это header__menu ) полностью решает задачу абстрактных блоков-оберток, отвечающих за внешнее позиционирование блока.

Удобство параллельной разработки

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

В качестве примера рассмотрим библиотеку блоков bem-components, которая содержит универсальные блоки, такие как ссылка, кнопка, поле ввода. Из универсальных компонентов легко создавать более сложные блоки. Например, селект или чекбокс.

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

Блоки в файловой структуре

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

Цукерберг рекомендует:  Тройка тенденций в области веб-дизайна

Реализация каждого блока хранится в отдельной папке проекта. Каждой технологии (CSS, JavaScript, тестам, шаблонам, документации, картинкам) соответствует отдельный файл.

Например, если внешний вид блока input задан с помощью CSS, то код будет сохранен в файле input.css .

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

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

Файловая структура любого БЭМ-проекта состоит из уровней переопределения. Уровни переопределения позволяют:

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

Шаблонизация в БЭМ

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

  • Сократить время на отладку проекта, так как изменения в шаблоне автоматически применятся ко всем блокам проекта.
  • Изменять разметку блока.
  • Переносить блоки с текущей разметкой в другой проект.

В БЭМ используется шаблонизатор bem-xjst, который содержит два движка:

  • BEMHTML — преобразует BEMJSON-описание страницы в HTML. Шаблоны описываются в файлах с расширением .bemhtml.js .
  • BEMTREE —преобразует данные в BEMJSON. Шаблоны описываются в BEMJSON-формате в файлах с расширением .bemtree.js .


Если шаблоны к блокам не написаны, шаблонизатор по умолчанию установит блокам тег

Сравните декларацию блоков и выходной результат HTML:

Чтобы изменить разметку блока menu , необходимо написать шаблоны для блока:

1. Меняем тег блока menu :

По аналогии с CSS, шаблон будет применен ко всем блокам menu на странице.

2. Добавляем дополнительный элемент ( menu__inner ), который выполнит функцию внутренней обертки и будет отвечать за расположение элементов внутри блока menu . Изначально элемент menu__inner не указывался в декларации, поэтому необходимо добавить его на этапе сборки шаблонов.

Шаблоны в БЭМ написаны на JavaScript, поэтому добавить новый элемент в шаблон также можно с помощью JavaScript:

3. Изменяем теги всем элементам inner и item :

5. Изменяем существующий шаблон. Правила в шаблонах применяются так же, как в CSS: нижнее правило перекрывает верхнее. Добавим новые правила в шаблон, изменим тег ссылкам с на :

Тестирование верстки

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

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

Сборка проекта

Для удобства работы с кодом в БЭМ-проекте все блоки и технологии разложены по отдельным папкам и файлам. Чтобы объединить исходные файлы в один (например, все CSS-файлы в project.css , все JS-файлы в project.js и т. п.), используется сборка.

Сборка решает следующие задачи:

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

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

Так как в БЭМ блоки разрабатываются независимо, находятся в разных файлах файловой системы, они ничего не знают друг о друге. Чтобы одни блоки могли строиться на основании других, необходимо указывать зависимости. За это отвечает отдельная технология в БЭМ — файлы deps.js . По файлам зависимостей инструмент сборки понимает, какие блоки дополнительно подключить в проект.

С чего начать?

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

Вёрстка графических компонентов

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

При создании графических компонентов («виджетов») в первую очередь придумывается их HTML/CSS-структура.

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

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

Семантическая вёрстка

HTML-разметка и названия CSS-классов должны отражать не оформление, а смысл.

Например, сообщение об ошибке можно сверстать так:

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

При семантической вёрстке классы описывают смысл («что это?» – меню, кнопка…) и состояние (открыто, закрыто, отключено…) компонента.

У предупреждения будет класс warning и так далее, по смыслу.

Семантическая вёрстка упрощает поддержку и развитие CSS, упрощает взаимодействие между членами команды.

Такая вёрстка удобна для организации JS-кода. В коде мы просто ставим нужный класс, остальное делает CSS.

Состояние виджета – класс на элементе

Зачастую компонент может иметь несколько состояний. Например, меню может быть открыто или закрыто.

Состояние должно добавляться CSS-классом не на тот элемент, который нужно скрыть/показать/…, а на тот, к которому оно «по смыслу» относится, обычно – на корневой элемент.

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

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

Или, к примеру, разметка для индикатора загрузки может выглядеть так:

Состояние индикатора может быть «в процессе» (loading) или «загрузка завершена» (complete). С точки зрения оформления оно может влиять только на показ внутреннего span , но ставить его нужно всё равно на внешний элемент, ведь это – состояние всего компонента.

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

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

Префиксы компонента у классов

Рассмотрим пример вёрстки «диалогового окна»:

Диалоговое окно может иметь любое HTML-содержимое.

А что будет, если в этом содержимом окажется меню – да-да, то самое, которое рассмотрели выше, со ?

Правило .dialog .title применяется ко всем .title внутри .dialog , а значит – и к нашему меню тоже. Будет конфликт стилей с непредсказуемыми последствиями.

Конечно, можно попытаться бороться с этим. Например, жёстко задать вложенность – использовать класс .dialog > .title . Это сработает в данном конкретном примере, но как быть в тех местах, где между .dialog и .title есть другие элементы? Длинные цепочки вида .dialog > . > .title страшновато выглядят и делают вёрстку ужасно негибкой. К счастью, есть альтернативный путь.

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

Здесь имя dialog , так что все, относящиеся к диалогу, будем начинать с dialog__

Здесь двойное подчёркивание __ служит «стандартным» разделителем. Можно выбрать и другой разделитель, но при этом стоит иметь в виду, что иногда имя класса может состоять из нескольких слов. Например title-picture . С двойным подчёркиванием: dialog__title-picture , очень наглядно видно где что.

Есть ещё одно полезное правило, которое заключается в том, что стили должны вешаться на класс, а не на тег. То есть, не h2 < . >, а .dialog__title < . >, где .dialog__title – класс на соответствующем заголовке.

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

На практике из этих правил зачастую делают исключения. Можно «вешать» стили на теги и использовать CSS-каскады без префиксов, если мы при этом твёрдо понимаем, что конфликты заведомо исключены.

Например, когда мы точно знаем, что никакого произвольного HTML внутри элемента (или внутри данного поддерева DOM) не будет.

Описанное выше правило именования элементов является частью более общей концепции «БЭМ», которая разработана в Яндексе.

БЭМ предлагает способ организации HTML/CSS/JS в виде независимых «блоков» – компонентов, которые можно легко перемещать по файловой системе и между проектами.

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

Более подробное описание основ БЭМ можно почитать в статье https://ru.bem.info/articles/bem-for-small-projects/, а о системе вообще – на сайте http://ru.bem.info.

Итого

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

Класс, описывающий состояние всего компонента, нужно ставить на его корневом элементе, а не на том, который нужно «украсить» в этом состоянии. Если состояние относится не ко всему компоненту, а к его части – то на соответствующем «по смыслу» DOM-узле.

Классы внутри компонента должны начинаться с префикса – имени компонента.

Это не всегда строго необходимо, но позволяет избежать проблем в случаях, когда компонент может содержать произвольный DOM, как например диалоговое окно с произвольным HTML-текстом.

Использование .dialog__title вместо .dialog .title гарантирует, что CSS не применится по ошибке к какому-нибудь другому .title внутри диалога.

Задачи

Семантическое меню

Посмотрите на вёрстку горизонтального меню.

Что делает эту вёрстку несемантичной? Найдите 3 ошибки (или больше).

Как бы вы сверстали меню правильно?

Несмотря на то, что меню более-менее прилично отображается, эта вёрстка совершенно не семантична.

Во-первых, меню представляет собой список элементов, а для списка существует тег LI .

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

и т.п.

Во-вторых, класс rounded-horizontal-blocks показывает, что содержимое должно быть оформлено как скруглённые горизонтальные блоки. Любой класс, отражающий оформление, несемантичен.

Правильно – чтобы класс был смысловым. Например,

    будет говорить о том, что смысл элемента – «меню».

В-третьих, элемент .vertical-splitter . Здесь класс вполне семантичен, этот элемент списка является вертикальным разделителем, так что здесь всё в порядке. Но на этот раз несемантичность – в содержимом.

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

Поэтому от него следует либо вообще избавиться, либо переместить в CSS при помощи ::before .

И, наконец, это не обязательно и не ошибка, но обычно элементы, которые являются ссылками или кнопками, оформляют в или .

Вариант ниже – семантичен:

Дополнительно, классы помечены префиксом компонента, на тот случай, если в заголовках появится произвольный HTML.

Правильный способ написания в соответствии с методологией BEM для следующей разметки?

Каков правильный способ записи по методологии BEM для следующей разметки:

Или:

У вас есть два блока: header и logo . Logo имеет элемент — image . Основная структура:

Сначала вы должны решить, действительно ли нужно обертывание div? Может быть, вы можете просто написать:

Так или иначе.
Если logo в header имеет некоторые пользовательские стили, например поля или разные размеры, вы должны добавить модификатор logo_modificator для настройки логотипа в header .

Что еще я рекомендую вам разделить col и header .

Что такое методология BEM?

Недавно я слышал о методологии BEM.

  • Что такое использование методологии BEM?
  • Как BEM облегчает нашу работу?
  • Хорошо ли использовать BEM?

BEM — это методология именования. Это означает модификатор Block Element, который нацелен на упрощение модульности и упрощение стилей и классов.

Это нелегко объяснить в ответ, но я могу дать вам основную идею.

Итак, если вы думаете о меню, то вся структура элемента/компонента будет:

Блок: Элемент Элемент: Модификатор (ы): горизонтальный, вертикальный

И, следуя стандартным соглашениям BEM, вы должны написать что-то вроде этого в CSS:

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

Теперь, если вы измените модификатор в меню от —horizontal до —vertical , специальные стили модификаторов будут выбраны как для блока, так и для элемента внутри.

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

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

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

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

Здесь используется прецедент, если вы хотите увидеть его в использовании в реальном проекте https://m.alphasights.com/how-we-use-bem-to-modularise-our-css-82a0c39463b0#.2uvxts71f

Надеюсь, это поможет:)

Что такое BEM?

BEM означает Blocks, Elements and Modifiers . Это методология, изначально задуманная российской технологической компанией Yandex. Как и следовало бы, методология BEM — все о компонентности вашего кода HTML и CSS в трех типах компонентов:

Блоки: автономные объекты, которые имеют смысл сами по себе. Примерами являются header , container , menu , checkbox и textbox

Элементы: Часть блоков, которые не имеют отдельного значения и семантически привязаны к их блокам. Примерами являются menu item , list item , checkbox caption и header title

Модификаторы: Флаги на блоке или элементе, используемые для изменения внешнего вида или поведения. Примеры: disabled , highlighted , checked , fixed , size big и color yellow

Цель BEM — оптимизировать читаемость, удобство обслуживания и гибкость вашего CSS-кода. Способ достижения этого — применить следующие правила.

  • Стили блоков никогда не зависят от других элементов на странице
  • Блоки должны иметь простое, короткое имя и избегать символов _ или —
  • При стилизации элементов используйте селектор формата blockname__elementname
  • При модификации стилей используйте селектор формата blockname—modifiername и blockname__elementname—modifiername
  • Элементы или блоки, которые имеют модификаторы, должны наследовать все от блока или элемента, который он модифицирует, кроме свойств, которые должен модифицировать модификатор.

Пример кода

Если вы применяете BEM к вашим элементам формы, ваши селектора CSS должны выглядеть примерно так:

Соответствующий HTML должен выглядеть примерно так:

Если вы используете BEM?

BEM приобрел немалую тягу среди американских и западноевропейских веб-разработчиков после популяризации влиятельных гуру CSS, таких как Harry Roberts. Это особенно популярно в сочетании с OOCSS и SMACSS (все это действительно вариации на тех же принципах написания модульного CSS). А модульный CSS имеет довольно много преимуществ. Однако модульный CSS может быть довольно многословным, и BEM, в частности, часто считается довольно уродливым.

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

Если вероятность того, что ваш код когда-либо будет поддерживаться разработчиками, у которых уже есть опыт работы с BEM/OOCSS/SMACSS, имеет важное значение, вы можете выбрать одну или несколько из этих методологий и строго соблюдать их приложение, просто потому, что это сделает сотрудничество с этими разработчиками намного проще. Если нет, есть небольшое преимущество строго придерживаться любого из этих конкретных конвенций, и вы можете свободно выбирать свои собственные соглашения об именах и свои собственные варианты на BEM/OOCSS/SMACSS. В конце концов, полезность любого стандарта во многом зависит от того, кто на самом деле его использует.

Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих