Блок BEM, именование и вложенность
Я пытаюсь склонить голову вокруг соглашения об именах BEM. Я застрял в этом. Я могу что-то недопонимать, давайте посмотрим.
У меня есть навигатор боковой панели и контент nav.
Моя боковая панель выглядит так:
<div class="sidebar">
<ul class="sidebar__nav">
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
</ul>
</div>
И мой контент nav выглядит так:
<div class="content">
<ul class="content__nav">
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
</ul>
</div>
Теперь я столкнусь с проблемой, если я использую стиль .nav__item, они встречаются как в моих навигациях, так и не должны иметь одинаковый стиль. Должен ли я делать некоторые вложения здесь, или я неправильно назову свои блоки и элементы?
Пример вложения в CSS:
.content__nav .nav__item { background: Red; }
Или я должен назвать это следующим образом:
<li class="content__nav__item"><a href="#" class="content__nav__link">LINK</a></li>
Вы можете помочь?
Ответы
Ответ 1
Существует несколько вариантов написания классов BEM, поэтому имейте в виду, что это несколько конкурирующих стандартов. Это началось как набор правил. После публикации ответа Яндекс значительно пересмотрел свой официальный стандарт (это довольно улучшилось). Версия BEM я используется в основном из статьи Николаса Галлахера.
В этот момент я использую "Atomic OOBEMITLESS" , что на самом деле является просто способом сказать, что классы являются модульными и именными, селектора имеют низкую специфичность, и состояния могут быть переключенным с классами, которые позволяют масштабировать CSS, поверх препроцессора CSS, чтобы сделать код более кратким и выразительным.
Все, что сказал, я буду использовать следующий стандарт BEM:
- имена дефисных классов в виде блоков:
foo-bar
- имя блока, за которым следует
__
, за которым следует дефинированное имя класса для элементов:
foo-bar__fizz-buzz
- имена блоков или элементов, за которыми следует
--
, за которыми следуют дефисные имена классов для модификаторов:
foo-bar--baz
, foo-bar--baz__fizz-buzz
, foo-bar__fizz-buzz--qux
Краткая форма BEM: block-name__element-name--modifier-name
В ваших примерах есть три разных блока:
-
sidebar
, который имеет элемент sidebar__nav
-
content
, который имеет элемент content__nav
-
nav
, который имеет элементы nav__item
и nav__link
Блоки sidebar
и content
выглядят вариациями одного и того же блока и могут быть представлены как .region.region--sidebar
и .region.region--content
.
Блок nav
неявна в элементе ul
, и вы должны сделать его явным:
<ul class="nav"><!-- could be content__nav or sidebar__nav as well if you choose -->
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
</ul>
Как только вы указали, что элемент ul
является блоком nav
, имеет смысл модифицировать блок nav
:
<ul class="nav nav--content">
<li class="nav__item nav--content__item"><a href="#" class="nav__link nav--content__link">LINK</a></li>
<li class="nav__item nav--content__item"><a href="#" class="nav__link nav--content__link">LINK</a></li>
</ul>
После того, как вы настроили классы CSS, стилизация всех элементов nav__item
проста:
.nav__item {
...styles here...
}
и переопределение этих стилей для элементов контента nav__item
:
.nav--content__item {
...styles here...
}
Ответ 2
Вероятно, вам стоит взглянуть на часто задаваемые вопросы BEM.
Каким будет имя класса для элемента внутри другого элемента? .block__elem1__elem2
?
Что делать, если мой блок имеет сложную структуру и его элементы вложены? Классы CSS, такие как block__elem1__elem2__elem3
, выглядят пугающими. Согласно методу BEM блочная структура должна быть сглажена; вам не нужно отображать вложенную структуру DOM блока. Итак, имена классов для этого случая:
.block{}
.block__elem1{}
.block__elem2{}
.block__elem3{}
В то время как представление DOM блока может быть вложенным:
<div class='block'>
<div class='block__elem1'>
<div class='block__elem2'>
<div class='block__elem3'></div>
</div>
</div>
</div>
Помимо того, что классы выглядят намного приятнее, он заставляет элементы зависеть только от блока. Таким образом, вы можете легко перемещать их по блоку при внесении изменений в интерфейс. Изменениям структуры DOM блока не нужны соответствующие изменения в CSS-коде.
<div class='block'>
<div class='block__elem1'>
<div class='block__elem2'></div>
</div>
<div class='block__elem3'></div>
</div>
Ответ 3
Рассмотрим идею пар _key_value
для модификаторов (блок или элемент отделен от имени модификатора одним подчеркиванием и его значением с другим).
Имеет смысл различать модификаторы один от другого (например, nav_type_content
и nav_type_sidebar
- это то место, где nav
apper на странице, но модификация темы, размера или создания ссылок через ajax различна) и поэтому, чтобы понять, какие модификаторы не могут использоваться вместе на одном DOM- node.
Также удобнее работать с парами ключ: значение в javascript.
И есть довольно много готовых компонентов и инструментов, которые используют такое соглашение: https://github.com/bem/