EN
tadatuta
tadatuta
21 октября 2015

Обертки бывают двух типов:

  1. Про расположение блока относительно других блоков
  2. Про лейаут внутри блока

Когда сталкиваетесь с первым случаем, чаще всего подойдет микс (либо с элементом родителя, либо с элементом сетки). Например:

<div class="some-parent">
    <div class="my-something some-parent__something">...</div>
</div>

либо

<div class="grid">
    <div class="my-something grid__col">...</div>
</div>

Еще можно не экономить на лишних DOM-узлах и делать так:

<div class="grid">
    <div class="grid__col">
        <div class="my-something">...</div>
    </div>
</div>

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

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

Если же обертка относится именно к данному блоку (скажем, позиционирование иконки внутри той самой универсальной кнопки или ограничитель по max-width для контента страницы), то это будет внутренний элемент inner:

<button class="button">
    <span class="button__inner">
        <span class="button__icon"></span>
    </span>
</button>

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

voischev
#voischev
22 октября 2015

@tadatuta :+1:

ihorzenich
#ihorzenich
22 октября 2015

Но чем по сути блок button__inner отличается от блока-враппера, обертки? Это же и есть обертка. Просто ей придумали «красивое» название. Нет?

tadatuta
#tadatuta
22 октября 2015

@delka

<div class="wrap">
    <div class="block"></div>
</div>

VS.

<div class="block">
    <div class="block__inner"></div>
</div>
ihorzenich
#ihorzenich
22 октября 2015

Т.е. разница в том что мы договариваемся считать их элементами блока, а не отдельными блоками (связанными названием или не связанными, тк получилось придумать логичное имя)?

<div class="block">
    <div class="block__inner"></div>
</div>

VS

<div class="block">
    <div class="block-wrapper"></div>
</div>

VS .block > .h-block, VS .l-block > b-block и т.д.

tadatuta
#tadatuta
22 октября 2015

Давай еще раз: h- и l- блоки — это как раз случай, когда есть некая внешняя сущность, отвечающая за лейаут. В моем примере — это блок grid. Это работает, когда позиционирование является абстрактным в вакууме. Например, у нас есть шаг сетки и он всегда такой во всех случаях использования.

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

При этом важно понимать, что это не блок logo (и даже не logo_type_header) имеет отступ 20 пикселей от границ шапки, а элемент шапки header__logo. Тогда logo можно будет использовать повторно где-то еще на странице и не перебивать каждый раз отступы, т.е. получится тот самый независимый универсальный блок.

ihorzenich
#ihorzenich
22 октября 2015

Для внутреннего позиционирования — понятно, используем элементы-врапперы, придумывая им красивые названия.
Но проблема с придумыванием имен для позиционирования внешнего — там бывает просто не знаешь что выдумать, а .l-block, .b-block — здорово выручают с неймингом. И бонусом получаем понимание смысла блока видимое из названия (то о чем пишет Гарри Робертс: http://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/)

tadatuta
#tadatuta
22 октября 2015

@delka

Я в посте написал буквально следующее: «на самом деле примерно никогда не нужно заворачивать конкретный блок в абстрактную обертку».

Можешь привести примеры макетов из реальной жизни, когда появляется необходимость в абстрактной внешней обертке не являющейся каким-либо аналогом сетки?

voischev
#voischev
22 октября 2015

@tadatuta я тоже не понимаю о чем вещает @delka и какие кейсы он решает.
По опыту примеры Вовы должны решать большенство кейсов

alex-milovanov
#alex-milovanov
28 октября 2015

Вопрос про внутреннее позиционирование: что делать если надо разместить обертку внутри элемента, а не блока? И как правильно именовать эту обертку?

tadatuta
#tadatuta
28 октября 2015

@alex-milovanov Ничего не меняется:

<div class="my-block">
    <div class="my-block__elem">
       <div class="my-block__inner"> <!-- либо my-block__elem-inner -->
       </div>
    </div>
</div>
JiLiZART
#JiLiZART
28 октября 2015

@tadatuta вот бы в FAQ это вынести :)

tadatuta
#tadatuta
28 октября 2015

это будет частью документа про БЭМ в HTML

jt3k
#jt3k
1 ноября 2015

С &_inner хороший вариант я же всегда делал элемент с именем outer__inner-block-holder

<div class="outer">
    <div class="outer__inner-block-holder">
        <div class="inner">

Но решение с inner в первом посте выглядит лучше, так как в этом случае мы не отрываем позиционирующий слой от самого блока. Спасибо!

ihorzenich
#ihorzenich
16 ноября 2015

@tadatuda @voischev
Привожу примеры когда нужна «абстрактная внешняя обертка не являющейся каким-либо аналогом сетки».

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

Оба варианты предлагаешь решать либо сеткой или внутренними блоками-элементами (и то и другое возможно с миксованием).

Когда я считаю такое такое не получается/неудобно?

  1. Расположение блока относительно других блоков: Когда блок уже находится на самом высоком уровне иерархии.
    Ну самый простой пример - sticky-баннер висящий на странице. Как напишем?
.banner {} // позиционирование баннера
.banner__item {} // сам баннер

Не, так мы баннер не сможем юзать в другом месте, мы не поставим где-то одиноко banner__item без banner, перепишем:

.banner-holder
  .banner-holder__item.banner
.banner-holder {} // никаких стилей, просто пустой блок в угоду БЭМ
.banner-holder__item {} // позиционирование баннера
.banner {} // сам баннер
.banner-holder__item.banner {} // микс баннера и его позиционирования

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

.banner-holder__item.banner
.banner-holder__item {} // позиционирование баннера
.banner {} // сам баннер

Но это не по правилам, исправим:

.banner-holder.banner
.banner-holder {} // позиционирование баннера
.banner {} // сам баннер

Правила не нарушены. Получили блок-холдер. По факту это тоже самое что и

.l-banner {} // позиционирование баннера
.b-banner {} // сам баннер

Чем это хуже чем

.banner-holder {} // никаких стилей, просто пустой блок в угоду БЭМ
.banner-holder__item {} // позиционирование баннера
.banner {} // сам баннер
.banner-holder__item.banner {} // микс баннера и его позиционирования
  1. Лейаут внутри блока: когда блоки нужно чем-то обернуть, а внутренние блоки выглядят высосанными из пальца
    Ну например у нас есть какие-нибудь бэйджи: картинки с подписями. Их 4 штуки, расположены внутри блока с текстом. Нужен блок-обертка, у которой будет например display: flex, а от неё на бэйджи пойдут стили для flex-элементов. Как напишем? Можно выдумать какой-нибудь дочерний элемент, но даже название для него кажется вымученным:
.content // блок с текстом
  .content__bagdes // враппер для бэйджев
    .badge // бэйдж

А погодите, какое вообще отношение элемент content__badges имееет к content? Он же никак не связан с .content, он стили для badge пилит! Не не годится, может давайте сетку?

.content
  .grid
    .bagde.grid-4

Было бы норм, но а если позиционирование в сетку не пишется, если оно какое-то нестандартное? Переименуем:

.content
  .badge-layout
    .badge

Но стоп, да это же опять блок-холдер вышел?!

А почему мы так стыдливо пытаемся отказаться от холдера, как будто это что-то неприличное? Да и разве БЭМ запрещал когда-то вкладывать блоки-в блоки? Нет. Так а зачем тогда нам так стараться всё связать миксованием и дочерними элементами?

Guria
#Guria
16 ноября 2015
  1. Если принять <body class="page">, то <div class="page__banner banner" />
voischev
#voischev
16 ноября 2015

@delka
в 1. много хорошего написано кроме h-, l- — лишнее.
Делать для конкретного блока обертку с таким же названием... ну не знаю. кажется стоит более реальный кейс приводить. Скорее всего прям обертку придумывать не придется — банер живет внутри приложения... там сильно больше других блоков от которых можно сделать микс или обертку более логично.

в 2. ну ты привираешь что бы склонить мнения людей к решению как тебе кажется лучшее, с префиксами (l-, h-). Но это не правда ;) не надо так делать ;)

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

zxqfox
#zxqfox
16 ноября 2015

Этот тредик — прекрасный пример как можно расходовать время в холостую ;-(

ihorzenich
#ihorzenich
16 ноября 2015

@voischev отставим вопрос префиксов, я в тех примерах упрощал до префиксов имена вида block / block-wrapper. Представь что я про префиксы не написал, остановился на предпоследних примерах.

tadatuta
#tadatuta
16 ноября 2015
  1. Если универсальный баннер позиционируется относительно страницы, то, как верно написал @Guria — за позиционирование отвечает элемент page (в результате никаких исключений для верхнеуровневых блоков, все консистентно).
  2. Про бейджи я не понял, почему бы не
<div class="content">
    <div class="badges">
        <div class="badge"></div>
        <div class="badge"></div>
        <div class="badge"></div>
    </div>
</div>
ihorzenich
#ihorzenich
17 ноября 2015

@tadatuda а в чем принципиальное отличие

.badges
.badge

от

.badge-wrapper
.badge
JiLiZART
#JiLiZART
17 ноября 2015

@delka из первого примера понятно что это список бейджиков, из второго нет.

ihorzenich
#ihorzenich
17 ноября 2015

@JiLiZART тогда мы приходим к тому что это просто вопрос «какое красивое название придумать», технически — это обычный враппер.

tadatuta
#tadatuta
17 ноября 2015

@delka технически в верстке всё — блочные либо инлайновые элементы ;)

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