Войти с помощью github
Форум /

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

У нас такая практика: есть блок, он описывает DOM-структуру, и к нему через модификатор можно цеплять один из заданных стилей для "раскраски". Например, меню:

<ul class="menu menu_style_main">
    <li class="menu__item"><a href="#" class="menu__link">One</li>
    ...
</ul>

И стили:

.menu_style_main .menu__link {
    font-size:20px;
    color:#F00;
}

...

.menu_style_alt .menu__link {
    font-size:12px;
    color:#666;
}

То есть используем разрешенный методологией каскад "блок-с-модификатором - элемент".

Приключения начинаются, когда дизайнер рисует меню, в котором верхние пункты расхлопываются в попап, внутри которого свой маленький мир, как назло включающий пару вложенных меню. Вот картинка (с первого попавшегося сайта), иллюстрирующая идею: http://joxi.ru/1A5pxGZfK6BoB2

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

Я вижу такие варианты:

  1. Явно описывать в CSS структуру блока, используя "стрелку": .menu_style_main > .menu__item > .menu__link - вроде не труЪ, привязываемся к структуре DOM, вынуждаем себя ее помнить и суппорить изменения в 10 местах.
  2. Спускать модификатор вниз на элементы, то есть вешать на все элементы блока правильный модификатор стиля: .menu__link_style_main etc. Если действовать в таком духе (учитывая, что проблема относится к любому модификатору блока), получим что-то типа pyramid of doom, но в стиле БЭМ - когда 90% html-кода расположены в атрибуте class. Vermicelli of BEM. Как минимум работа со вкладкой Elements консоли разработчика станет очень грустной.
  3. Считать, что это не один блок, а разные (по сути тупо переносим название стиля в имя блока): .menu-main .menu-main__link {...} Во-первых, похоже на предыдущий вариант (приклеиваем название стиля ко всем элементам, только не как модификатор, как часть имени блока). Во-вторых, это все-таки один блок - семантика та же, поведение для JS то же, выглядит только иначе.
  4. Сделать, чтобы вложенное меню на самом деле не было вложенным на уровне DOM (положить рядом и спозиционировать). Неудобно и не реализуемо для других случаев.
  5. Забить на все и тупо инлайнить стили прямо в HTML. Не канает, мы не SPA, собирать это все придется на сервере (а там PHP), и потом еще как-то дублировать поведение на клиенте.

Другие примеры "рекурсивности":

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

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

Кто что посоветует, кто сталкивался с подобными траблами? Сейчас мы используем вариант №1 (селектор прямого потомка), и я склоняюсь к варианту №2 (перенести модификатор на элементы). Потому что зеркалить dom-структуру в CSS приходится руками, а развесить модификаторы мы можем автоматом. И второй вариант вроде бы валиднее с точки зрения методологии.

Расскажите ваши мысли, и может я что-то вообще упускаю? Спасибо )