В чем смысл явного именования классов потомков BEM при наличии SCSS?

Я пытаюсь понять и понять причины, стоящие за соглашениями об именах CSS, такими как BEM или SUITCss. Мне трудно понять значение имен классов потомков в присутствии SCSS.

Например:

<ul class="menu">
    <li class="menu__item"></li>
    <li class="menu__item"></li>
    <li class="menu__item">
        <a href="#" class="menu__item_link">link</a>
    </li>
</ul>

.menu {
    .menu__item { 
      //styles
      .menu__item__link { //styles }
    }
    //or alternatively this syntax..
    &__item { //styles }
}

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

Почему бы и нет:

<ul class="menu">
    <li class="item"></li>
</ul>

.menu {
    .item {//styles}
}

Я понимаю, что соглашение об именах потомков более явное и, возможно, более благоприятное для будущего. Я утверждаю, однако, что это только более явно в HTML. Если бы я хотел проконсультироваться с тем, как создать этот модуль "меню", я мог бы просто обратиться к CSS и так же ясно увидеть, как в меню есть элементы, вложенные внутрь.

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

.menu { //styles }
.menu__item { //styles }
.menu__item__link { //styles }

А затем используйте "menu__item" в любом месте, и в имени класса все равно будет ясно, что это стиль элемента в меню... но тогда зачем вообще определять его как потомка меню? (Полагаю, еще одним преимуществом является более короткая строка идентификатора CSS, если что-то не вложено)

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

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

2 ответа

Несколько замечаний.

1 / Во-первых,

.menu {
    .menu__item { /* ... */ }
    //or alternatively this syntax..
    &__item { /* ... */ }
}

Два синтаксиса SCSS не эквивалентны. Первый использует каскад (".menu .menu__item"), а не второй (".menu__item"). Только второй соответствует БЭМ.

2 / Почему не каскад:

.menu {
    .item { /* styles */ }
}

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

Но каскады не свободны от контекста. В вашем примере есть блок "menu", который содержит элемент "item". Контекстом элемента "item" является блок "menu". Но каскад нарушает разделение контекста для подблоков. Префиксный синтаксис BEM допускает вложение блоков, а каскад - нет. Например:

<ul class="menu">
    <li class="menu__item"></li>
    <li class="menu__item">
        <div class="other-block">
            <span class="other-block__item"></span>
        </div>  
    </li>
</ul>

Обратите внимание на элемент "item" в подблоке. С каскадом вместо префикса это будет стилизовано правилом, которое будет нацелено на элементы "item" родительского блока.

3 / Это имя класса не соответствует БЭМ:

.menu__item__link { /* styles */ }

Элементы не предоставляют никакого контекста. Только блоки предоставляют контексты. Контекст элемента является контекстом его блока. Таким образом, "ссылка" не является потомком "элемента" в дереве БЭМ. Эти два брата, независимо от их ситуации в дереве DOM. Вы должны использовать:

.menu { /* styles */ }
.menu__item { /* styles */ }
.menu__link { /* styles */ }

Давайте начнем с идеи БЭМ или SMACSS.

Основная задача, которую решает любая методология, - структурирование и модульность вашего кода.

Например, БЭМ использует следующие абстракции:

Блок - независимая часть пользовательского интерфейса (например, форма обратной связи),

Элемент - часть блока не может существовать без блока (как кнопка формы обратной связи),

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

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

1) BASE - вы добавляете css reset, определяете размеры шрифта H1, H2 ..., определяете цвета. Таким образом, в базу вы положили вещи, которые должны быть изменены.

2) LAYOUT - добавляет сетки или отдельную страницу в регионах. 3) Модуль - независимый элемент контента

3) СОСТОЯНИЕ - очень близко к модификатору БЭМ, но связано с некоторыми действиями с модулем, такими как is_hided, is_collapsed

4) Тема - может использоваться для переопределения BASE.

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

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

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

Другие вопросы по тегам