Pull to refresh

Comments 81

UFO just landed and posted this here
блок отделяется двумя подчёркиваниями, а модификатор — двумя дефисами.
.block {}
.block--mod {}
.block__element {}
.block__element--mod {}

Элемент, а не блок, отделяется двумя подчеркиваниями?
Может я не прав, но поскольку определяется модификатор «block__element--mod», то возможно правильно написать — "имя элемента отделяется двумя подчёркиваниями, а имя модификатора — двумя дефисами"

https://ru.bem.info/methodology/quick-start/#Модификатор
В документации, в примерах, пишут без дефиса.
Меньше путаницы — легче новичкам.
Лучше бы либо доку переписать либо в учебных статьях подправить.

Подскажите, в «search-form search-form_focused», имя модификатора это «search-form search-form_focused» или «search-form_focused»?
В данном примере названием модификатора выступает «search-form_focused».
БЭМ не разделители и подчеркивания. Разделять можете как Вам нравится. Главное показать отношение элемента к блоку и их модификаторы.

Тут имя модификатора — focused

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


<div class="note">
    <div class="note__sidebar">
        <div class="note__sidebar__title">
            <img class="note__sidebar__title__icon"/>
        </div>
    </div>
</div>

И думал что это какая-то фигня, а потом я понял, что надо так:


<div class="note">
    <div class="note__sidebar">
        <div class="note__title">
            <img class="note__icon"/>
        </div>
    </div>
</div>

И я прозрел

UFO just landed and posted this here
Теперь и я прозрел. Спасибо.

Удивительно, как такой лаконичный пример никто раньше не привёл
Я тоже в свое время прозрел на этот счет
Отдельно добавлю, что если все таки нужно положить элемент в элемент, то для этого можно использовать одинарное подчеркивание. В связи с этим и удобно использовать именно — как разделитель для модификатора:
note__sidebar_title--size_m

Мы для отделения слов внутри имени используем -, а не _

Тогда все сольется в один большой элемент
front-page__section-promo-subinfo-title
против
front-page__section-promo_subinfo-title
или даже
front-page__section-promo_subinfo_title
Необходимость возникает когда title в блоке действительно не один, а делить все на микроблоки уже слишком
Нет ничего плохого в front-page__section-promo-subinfo-title. Зато тут програмно можно определить, что front-page это блок, а section-promo-subinfo-title — элемент.

Но я бы скорее сделал front-page__section и front-page__subinfo-title
Элементы в элементы запросто кладутся, но остаются элементами самого блока.

<div class="header">
    <div class="header__button">
        <div class="header__button-icon"></div>
        Button
    </div>
</div>


К слову, переиспользуемые компоненты — это тоже блоки, только они являются элементами другого блока («примешиваются» к нему). Например:
<div class="header">
    <div class="button header__button">
        <div class="button__icon"></div>
        <div class="button__text">Button</div>
    </div>
</div>


А дальше смело оформляйте через button все кнопки, а через header__button меняйте эту конкретную. Получается вполне классическое наследование.

Во втором примере как вы поменяете цвет иконки в кнопке в шапке, если "кнопка с иконкой" — отдельный переиспользуемый компонент со своим отдельным шаблоном?

Не понял, о чём вы.

.header__button .button__icon {
    background: red;
}

Так?

Именно. Надо ли объяснять чем это плохо?

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

Да нет, это проблемы из практики. Собственно для решения этих проблем БЭМ и появился. И он замечательно их решает в случае статических страниц. Для использования же в компонентах, нужно сделать ещё один шаг в том же направлении — нужен механизм "каскада", но на уровне компонент, а не дом-дерева. Пресловутый .header__button — это каскад второго уровня. Но уровней бывает нужно больше и тогда БЭМ откатывается обратно до использования дом-каскада. А всего-то, нужно позволить многоуровневый каскад .header__button__icon, но такие классы руками уже не попишешь — нужна автогенерация. У нас она есть. В случае bemhtml, на сколько я понял, есть только костыль с подсовыванием css-классов через данные.

1. Не понял эту претензию.
значит в дальнейшем перебивать его придётся не менее специфичным селектором
Что в этом плохого?
и дублировать стили для увеличенной специфичности (всякие ховеры, фокусы и тп, например)
Так вроде бы не дублировать, а переопределять только некоторые свойства CSS?

Типа так:
.header__button .button__icon, .header__button .button__icon:hover {
    background: red;
}
.header__button .button__icon:hover
{
    font-size: 22;
}
Правда я уже несколько лет не писал CSS так что не уверен. Сейчас как раз освежаю знания.

А что вы предлагаете? Вроде CSS специально так и работает.

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

3. Пункт принят.
  1. Речь о такой фигне:

/* иконку делаем полупрозрачной */
.button__icon {
    opacity: .8;
}

/* при наведении делаем её непрозрачной */
.button__icon:hover {
    opacity: 1;
}

/* в шапке хотим ещё более прозрачную кнопку */
.header_button .button__icon {
    opacity: .5;
}

/* чиним сломавшийся на предыдущем шаге ховер-эффект */
.header_button .button__icon:hover {
    opacity: 1;
}

  1. Они могут быть вложены друг в друга даже. Ну это не про кнопки, конечно, а про списки, например.
Самая главная проблема тут — нарушение инкапсуляции. По-хорошему, блок знает только про свои элементы и обращается к ним, а в этом примере блок header обращается к элементам блока button, что ведёт к очень болезненному рефакторингу, когда изменится внутренняя структура блока button.

ru.bem.info/methodology/css/#Принцип-открытостизакрытости
UFO just landed and posted this here
> Если поле нужно растянуть на всю ширину, но только в шапке, то блоку или элементу, который отвечает за это растягивание, даётся модификатор.

А мы не так делаем. Мы разделяем «внешние свойства» — все что за border-ом — типа padding, position, width; и «внутренние свойства» — все остальные. Блок верстается резиновым, и не задает сам «внешние» свойства. А его потребителям — позволено невозбранно навешивать на чужой блок селекторы своих элементов — которые его ставят как им надо. Очень удобственно. Ну типа так:
<div class='my-panel'> <!-- .my-panel { display: flex } -->
  <!-- .my-panel__item { flex: 1 1 auto; margin: 10px; } -->
   <div class='my-panel__item ui-button'>
     <div class='ui-button__caption'>HI</div>
   </div>
</div>


Ну и CSS Modules пробуем. Есть и плюсы, и минусы.
навешивать на чужой блок селекторы своих элементов
Не могли бы пояснить что это значит, JavaScript пишет типа block.className += " button_selector"?
Или копируется разметка, затем верстальщик ручками вписывает нужные селекторы?
Может вы о чем то другом.
Суть не в том, как именно class навешивается. Суть в том, что есть договоренность:
— компонент (блок) сам себе не задает margin/position/flex/width
— компонент верстается так, чтобы если его растянули — он бы нормально выглядел
— потребитель компонента сам вешает ему margin/flex/и т.п., чтобы его как нужно вставить

Т.е. если у нас кнопочка — она без паддингов и резиновая. Если кнопочку надо вставить и, скажем, растянуть пошире и отодвинуть справа — мы на нее вешаем flex и padding снаружи. Можно классом, можно инлайном — тут не суть. Это, вроде как, не чистый BEM, но нам так сильно проще жить.
Это называется «миксины».
Примешивание блока к элементу. Таким способом удобно позиционировать блоки внутри других блоков.
з.ы. это было мое второе «прозрение», как говорят в комментах выше.
Прикольно. Честно не знал, думал это мы додумали. Да и автор в статье вон, как пример, предлагает модификатором блок по ширине растягивать.
Если я правильно понимаю, вы говорите про классы типа color-red и т.п.
Проблема в том, что они ничего не говорят о состоянии блока / элемента, и по факту аналогичны внутренним стилям.

Когда вы пишете:
$elem.addClass('color-red');

— это абсолютно то же, что и
$elem.css('color', 'red');


И даже если вы добавите элементу состояние color-red как модификатор, это всё равно не очень хорошо: оно ни о чём не говорит.
$elem.addClass('elem_color-red');


Правильно делать вот так:
$elem.addClass('elem_warning');


Вот так всё становится простым и очевидным — класс переключает элемент в состояние warning. Если вы потом захотите, чтобы при warning текст не только становился красным, но ещё и мигал, вам не придётся бегать по всему js-файлу, правя класс на color-red-blink или elem_color-red-blink, а всего лишь исправить стиль у elem_warning.
(стоит сказать, что если делать elem_color-red, то тоже не придётся — БЭМ уже здесь начинает выполнять своё предназначение)
Благодаря этому блоки можно легко менять местами, вкладывать друг в друга и не бояться конфликтов или влияния.
Это надуманная проблема, в реальной разработке в такой гибкости нет необходимости. Те элементы, у которых позиция в разметке может измениться, должны верстаться с учетом возможных изменений и без всяких БЭМ. Среди остальных элементов в любом случае будут элементы, изменение позиции которых потребует изменения стилей, это уже вопрос дизайна и БЭМ здесь ничего не решает.
БЭМ решает проблему того, что в процессе разработки вдруг необходимо на страницу добавить блок, который есть на соседней. А этот блок разработчик мог написать с селектором типа .my-page .my-block и в итоге нужно или на новой странице добавлять класс .my-page, что может дать проблемы или оставлять в стилях только .my-block, но тогда его стили могут уже как-то переопределяться в будущем. Разработка же не заканчивается на этом.
Кроме того одним махом решается вопрос поддержки — намного проще изменить внутри блока какой-то элемент зная, что он точно изменится везде, а не нужно перепроверять все страницы, где этот элемент может быть.
Блоки, которые могут использоваться ну других страницах или еще где-то должны верстаться без зависимостей в любом случае. В рамках спецификации можно найти много изящных способов, как сверстать элемент полностью самостоятельным и независимым. БЭМ здесь ничего не решает, только уродует и ограничивает.
БЭМ задает удобные и простые правила как верстать _все_ компоненты полностью самостоятельными и независимыми из коробки

Это не надуманная проблема если в твоей жизни была фирма с общим фирменным стилем на всех сайтах.

Пока что единственные 2 момента меня останавливают от использования БЭМа:
1. Трудно читаемый код с такими длинными классами (в частности html-код)
2. Нет проектов с более, чем 2-мя верстальщиками
Там тулинг же надо, руками это писать — мазохизм. В LESS и прочих — дублирование убирается через вложенность правил. А в шаблонах или коде — тоже придумываются хелперы. Скажем, в реакте у нас:
const b = new Bem('my-button'); // один раз вверху модуля

b.div({ element: 'caption', mods: [isRed && 'red'] }); // my-button__caption my-button--red -->

У нас нет выделенных верстаков вообще, разработчики всё делают — и JS, и верстку. И всем удобно. Правда, мы уже теперь на CSS-модули переезжаем — они фичи БЭМ-а перекрывают, но суть та же.
Трудно читаемый код с такими длинными классами


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

Нет проектов с более, чем 2-мя верстальщиками


Это еще одно заблуждение. Даже одному писать код по единым понятным правилам намного проще, чем каждый раз придумывать новое решение, конфликтующее с предыдущим.
идея бема хорошая, а реализация неудобная, вот почему бы не договориться, что модификаторы должны содержать глаголы is, has, и не использоваться самостоятельно, тогда можно писать типа
.button.is-disabled {}

<button class="button is-disabled" />

вместо

.button--disabled {}

<button class="button button--disabled" />

Я с бемом использую модификаторы — полет нормальный

UFO just landed and posted this here
при использовании миксинов это может быть проблемой, но во-первых я не понимаю вообще смысл миксинов, т.к. в итоге блок становится винегретом из классов, понять как будет вести себя блок очень сложно на первый взгляд
<div class="menu__item button button_active">...</div>

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

ps: я честно не пишу по бэму, и если бы мне попался уже написанный проект с кодом типа
<div class="menu__item button button_active">...</div>
то мне было бы сложно его поддерживать
Как вы решаете задачу, чтобы кнопка могла быть использована в совершенно любом контексте, могла иметь опциональное активное состояние и при этом, будучи конкретно в пункте меню, обладала определенными отступами от контейнера? Каждый раз создаете лишние DOM-узлы?
Вы задали очень хороший вопрос. Все компоненты не имеют своих отступов, любые отступ должны задаваться из вне, чтобы спозиционировать ту же кнопку на странице используется или сетка, или специальные классы хэлперы, которые добавляют маржен или паддинг.
Я использую vuejs, и например маржен я могу задать через директиву, директива довольно функциональна, так же имеет модификаторы для медиа запросов
<menu>
    <v-button v-margin.xs.top="1" v-margin.md.top="2">
        send
    </-v-button>
</menu>


второй очень важный момент, что каждый компонент имеет свой файл со стилями и при импорте вебпак добавлят к названиям классов хэш, что гарантирует уникальные названия классов, чтобы уж наверняка. В моих шаблонах вы никогда не увидите классы, любые стили должны приналежать компоненту и построение шаблонов строго теми средствами, которые предоставляются в проекте, сетка+хэлперы/директивы
Я пробовал писать так, такие модификаторы действительно создают путаницу.
Наверное, можно, но это сложнее.
Зачем в модификаторе повторять всю цепочку названия? Моя верстка в общем следует бэму, только все модификаторы, и только они, начинаются с `-` т.е. вместо
<button class="search__button search__button--primary">
идет просто
<button class="search__button -primary">
Полагаю, чтобы не напороться на глобальный -primary
На глобальный search__button--primary тоже можно напороться. Но так да, название длиннее, вероятность меньше.
Эта проблема уходит вместе с использованием jade.
Код по типу
+b.block
+e.element_mod

преобразуется в
<div class='block__element block__element_mod>


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

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


[block1] {}
[block1~="mod"] {}
[block1_element1] {}
[block1_element1~="mod"] {}

[block2] {}
[block2~="mod"] {}
[block2_element2] {}
[block2_element2~="mod"] {}

[block1_element1_element2] {}
[block1_element1_element2~="mod"] {}

Более живой пример:


[header]{}
[header~="big"]{}
[header_query]{}

[suggest] {}
[suggest_option] {}
[suggest_option~="first"] {}

[header_query_option~="first"] {}

Ну и плюс ваши "уровни переопределения", только без лишней абстракции:


/* Первая подсказка в поле поиска на главной странице */
[serp_header_query_option~="first"] {}

Фактически получается каскад, но не на уровне ДОМ, а на уровне дерева блоков, и без проблем со специфичностью. Сами компоненты в доме могут располагаться друг относительно друга как угодно. Например, suggest может рендериться в body.


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

Мы БЭМ классы генерируем автоматически на основе:


  1. Имени блока (mol_button, например).
  2. Имени блока в контексте другого блока (блок mol_button, например, может иметь имя option в контексте mol_select, что даст селектор mol_select_option).
  3. И так далее по дереву компонент.

Пример из жизни:


<input
    id="$mol_app_todomvc.Root(0).Task_row(1).Title()"
    mol_app_todomvc_task_row_title
    mol_string
    mol_view
    placeholder="Task title"
>

[mol_view] {
    /* Общие стили для всех блоков, на этот селектор можем повесить всякие css-reset */
}

[mol_string] {
    /* Стили для блоков ввода строки текста */
}

[mol_app_todomvc_task_row_title] {
    /* Стили для блоков ввода текста задач в конкретном ToDoMVC приложении */
}

Ну а в "шаблоне", конечно, никакого БЭМ-а:


<= Title $mol_string
    hint <= title_hint @ \Task title
    value?val <=> title?val \

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


https://ru.bem.info/methodology/naming-convention/

Я вам предлагаю сделать шаг вперёд и понять, что элемент — это тоже блок, только в пространстве имён другого блока.

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

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

У нас всё сделано из компонент (блоков) у каждого из которых свой шаблон. И мы можем добавить произвольный класс элементу или в шаблон компонента (bemhtml) или на уровне данных (bemjson).
Когда нужно что-то изменить в готовом компоненте, создаётся модификатор этого компонента на своём уровне, в котором точечно доопределяются/переопределяются элементы этого компонента, добавляя нужные миксы к другим элементам этого компонента или к другим компонентам.

Это позволяет не писать стили вида

.my-component__element .foreign-component__element

а писать

.foreign-component_my-style .foreign-component__element

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


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


  1. Абстрактная иконка (ya-icon) текущего цвета
  2. Абстрактная строка поиска (ya-search) с кнопкой перехода (ya-search__go ya-icon)
  3. Шапка портала (ya-header) со строкой поиска (bt-header__search ya-search) и меню выбора сервиса.
  4. Главная страница биткоин-сервиса (btc-morda) с шапкой (btc-morda__header), телом и подвалом.

Задача: перекрасить кнопку перехода в строке поиска в шапке на морде биткоин-сервиса в золотой цвет. Как вы это сделаете?

UFO just landed and posted this here

У меня-то нет помойки. Я просто напишу в /btc/morda/morda.view.css:


[btc_morda_header_search_go] { color : gold }

Ок, не абстрактная, а конкретная иконка (ya-icon-search ya-icon). Если вопрос в том, зачем отдельный блок, то затем, чтобы через css можно было ею управлять. Например, чтобы текущий цвет шрифта был основным цветом иконки.

UFO just landed and posted this here

Вода камень точит :-) Впрочем, $mol я им даже не предлагаю. Хотя, было бы интересно послушать конструктивную критику, ведь он создан в том числе и для решения "портальных" проблем. Интересно, яндексоиды вообще заходили на страницу проекта, хотя бы просто посмотреть "как оно у них сделано", а то и стащить себе пару-другую свежих идей?


Вообще, забавно, как на базе идиомы непротиворечивого нейминга css-классов (прорывной для своего времени) эволюционно выстроилась целая экосистема для создания веб-приложений. Этакая геометрия Лобачевского: на базе чуть другого набора аксиом — совершенно другие результаты, довольно странные результаты. Для компонент куда естественней было бы использовать классы (Блоки) и свойства (Модификаторы — свойства, возвращающие примитивы, Элементы — свойства, возвращающие вложенные компоненты). Если проектировать сейчас (в 2017) "фреймворк от Яндекса" с чистого листа, думаю никакого БЭМ-а и в помине бы не было, как и зависимости от jQuery и кучи DSL-ей. Зато была бы статическая типизация и реактивное программирование.


Экосистема БЭМ сейчас стагнирует: морально устаревшие подходы, куча велосипедов, туча легаси-кода на них. Всё это ни переписать, ни отрефакторить, ни даже просто признаться, что последние 10 лет шли не туда. Яндекс имеет ресурсы и авторитет, чтобы двигать индустрию вперёд, а вместо этого побирается у Фейсбука, прикручивая его совершенно бестолковую поделку (React) к своему неконкурентноспособному велосипеду. Оно и понятно, ведь с подобным кодом в 2017 никто связываться не захочет:


// своя система модулей
// только динамическая типизация
modules.define(
    'hello', // имя блока
    ['i-bem-dom', 'input'], // подключение зависимости

    // функция, в которую передаются имена используемых модулей
    // очень удобно, когда зависимостей десяток
    function(provide, bemDom, Input) {

        // декларация блока
        // нам ведь всегда нужна асинхронная инициализация
        provide(bemDom.declBlock('hello', {

            // конструктор для описания реакции на события
            // событийная модель, замаскированная под реактивную
            onSetMod: {
                'js': {
                    'inited': function() {

                        // любой вложенный элемент нужно сначала найти
                        // а если он изменится - не забыть обновить ссылку на него
                        this._input = this.findChildBlock(Input);

                        // DOM-событие, на которое будет реакция
                        this._domEvents().on('submit', function(e) {

                            // предотвращение срабатывания события по умолчанию:
                            // отправка формы на сервер с перезагрузкой страницы
                            e.preventDefault();

                            // к чёрту консистентность, инварианты, единый источник истины, слои абстракции
                            // херачим текст прямо в элемент
                            this._elem('greeting').domElem.text('Привет, ' +
                                this._input.getVal() + '!');
                        });
                    }
                }
            }
        }));
    });
Ну даже не знаю… :)
Я же правильно понимаю, что приведенный сниппет кода должен ярко иллюстрировать ущербность БЭМа?

Она в том, что
1. Среди возможностей есть по-настоящему асинхронная во всех смыслах модульная система, позволяющая при необходимости точечно переопределять любые модули (стоит ли говорить, что ее использование опционально и БЭМ не перестанет быть БЭМом без нее?)
2. Помимо возможности декларативно описать реакцию на изменение модификаторов, можно воспользоваться и соответствующими событиями, которые обладают всеми возможностями нативных событий.
3. При необходимости отменить поведение события по умолчанию, нужно (о мой б-г!) вызвать preventDefault().
4. В hello-world примере не стали задвигать телегу про единый источник истины, докручивать флакс с привкусом редакса и прочие свистелки, которые каждый имеющий голову разработчик выбирает для себя сам и которые не имеют прямого отношению к тем вещам, за которые отвечает БЭМ.

Все верно? Ничего не упустил? :)
  1. В JS уже есть стандартные модули — стоит использовать их. Отложенная загрузка легко реализуется через механизмы реактивного программирования, без необходимости превращать код модуля в лапшу из колбэков. Пример с догрузкой ваших Я.Карт по требованию. И, кстати, да, у вас слишком много "опционального" и "вариативного". В итоге, в ваших исходниках сложно разбираться и ещё сложнее понять "как писать правильно".


  2. Это не декларативное описание реакции. Реакция весьма императивная. Претензия моя тут касалась необходимости искать элементы. Опять же у вас там используется два разных API для поиска, два разных апи для событий. И это всего-лишь в рамках HelloWorld. Уверен есть и ещё парочка с поиском по селекторам и делегацией событий в духе jQuery.


  3. Это не мой комент, а оригинальный. Собственно у меня тут претензий нет.


  4. Вот именно что, грамотный код (а это не про флаксоредаксы) было написать лень. И так кода целая гора получилась. Туториал должен учить как правильно, а не как наговнякать по быстрому. Для сравнения — привет мир на $mol — никаких скидок на то, что это "привет мир" — полноценное приложение, выполненное по всем канонам. И кода на порядок меньше, чем у вас.

Ничего не упустил?

Вы чудеснейшим образом не заметили то, что не используете.


  • Отсутствие статической типизации. Без неё работа над большими проектами крайне не эффективна.


  • Отсутствие реактивности. Без неё багоёмкость и избыточность кода слишком высока.


  • Отсутствие связывания данных. Без него композиция компонент затруднена и требует кучу инфраструктурного кода.


  • Отсутствие библиотеки высокоуровневых компонент. Вот это — даже до бутстрапа не дотягивает. Уж за столько человеколет должна была бы уже сформироваться библиотека готовых переиспользуемых решений. А нет, видимо ваши компоненты получаются совсем не переиспользуемыми.
UFO just landed and posted this here
с БЭМом явно что-то не так, и это не только читабельность кода, иначе не было бы столько холивара
Утверждение примерно в духе «с Windows явно что-то не так, и это не только необходимость перезагружаться при установке обновлений, иначе не было бы столько холива».

Тот факт, что про холивары про БЭМ не утихают во фронтенде ТАК долго уже о чем-то да говорит. Сколько технологий родилось, поднялось на волне хайпа и было забыто, пока нас ругают за читабельность кода, а потом пишут комментарии в духе habrahabr.ru/company/htmlacademy/blog/337286/#comment_10428564? ;)
UFO just landed and posted this here

Давно слышу про bem, но недавно впервые столкнулся с проектом, где бьют по рукам за :first-child, :last-child и прочие не бэмославные селекторы. Чувство дискомфорта не покидает с этим bem'ом. И даже не потому что надо писать километровые классы. Есть ощущение, что он отправляет нас куда-то в каменный век css 1. Ни тебе иерархий, ни первых/последних элементов, ни атрибутов. Только классы-классы-классы… Может Яндексу от этого и хорошо, но в среднем проекте это просто бессмысленное раздутие html, которое делает его плохо читаемым. При наличие аккуратного убористого css всё выглядит намного понятнее. Особенно если вы не хотите по пять раз на дню менять местами форму логина, блок спецпредложений, корзину заказа и новости.


К Яндексу в целом я отношусь хорошо, но Яндекс продвигает Яндекс. А bem — просто ещё один информационный повод с помощью которого проводится продвижение. Помнится, они когда-то и xslt продвигали. Я его даже учил и на нём писал. И где он сейчас? При том что возможности у него действительно большие, сложность в 99% проектов не оправдана. Надеюсь что и bem'овская эпидемия канет в Лету и мы снова сможем верстать трёхстраничные сайты просто на css 3.


P.S.: Открыл главную страницу Яндекса. Я просто оставлю это здесь:


<div class="i-bem popup dropdown-menu__popup dropdown-menu__popup dropdown-menu__popup_list_yes dropdown__popup dropdown__popup popup_domik_trigger popup_user_yes popup_theme_ffffff popup_autoclosable_yes popup_adaptive_yes popup_animate_yes" data-bem="{&quot;popup&quot;:{&quot;directions&quot;:{&quot;to&quot;:&quot;bottom&quot;,&quot;axis&quot;:&quot;right&quot;,&quot;offset&quot;:{&quot;top&quot;:-44,&quot;left&quot;:5}},&quot;disableoutside&quot;:&quot;yes&quot;}}" role="menu">...</div>

Вы правда хотите видеть такой html в своём проекте?

два чая этому господину

и вообще если у меня компонент имеет структуру ul > li, то почему я не могу написать
.list-component > li

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

или может мы не будем использовать даже :hover, а будем навешивать
list-component__item list-component__item--hover
БЭМ не запрещает использовать :first-child и прочие псевдоклассы.

Не рекомендуется использовать селекторы на теги и каскад от внутренностей одного блока к другому блоку / его элементам.
Про псевдоклассы я с ходу не нашёл внятных упоминаний на bem.info А под каскадом вы что имеете в виду? ">" и "+"? Вообще было бы здорово если бы помимо этой тугой документации был нормальный cheatsheet. Список css-слекторов с пометками «можно», «нельзя» и «можно только как в примере». Впрочем, может уже и поздно. Джин вылез из бутылки и теперь у каждого немножечко свой bem.
Так хорошо

.block_theme_big .block__elem

А так плохо

.block .another-block__elem
Если запрещать псевдоклассы типа :last-of-type, то с таким подходом можно еще и запретить использование :hover, :focus и т.п. =)
Sign up to leave a comment.