В чем смысл явного именования классов потомков 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, легко объяснить новым членам команды, как организован код и как писать новый код, который выглядит как написанный одним человеком.
Это чрезвычайно важно в крупных проектах с большими командами.
Кроме того, соглашение об именах помогает вам уменьшить количество потомков селекторов, которые улучшают производительность.