Что не так с квалификацией тега CSS (например, h1.some-class)?
Может кто-нибудь, пожалуйста, объясните мне причины, по которым проверка тегов является плохой практикой CSS? Почему tag.class является плохим в случаях с самообновленными элементами?
Например.
<section class="carousel-item">
<header class="header of-carousel">
<h2 class="heading of-carousel">Services</h2>
</header>
…
<footer class="footer of-carousel">
…
</footer>
</section>
Почему это должно быть лучше, чем DRY и сжатый код с модификаторами контекста?
<section class="carousel-item">
<header class="of-carousel">
<h2 class="of-carousel">Services</h2>
</header>
…
<footer class="of-carousel">
…
</footer>
</section>
.of-carousel {
header.& {…}
h2.& {…}
footer.& {…}
}
Или даже
section.carousel-item
header
h2
footer
.carousel-item {
header {…}
h2 {…}
footer {…}
}
Я вижу, что многие люди пристрастились к BEM, но я не понимаю, почему?
Их селекторы настолько уродливы, особенно - в-HTTP-2__ времени.
Ответы
Ответ 1
Соглашение, с которым я знаком, заключается в том, что квалификация является плохим, если селекторы имеют разные уровни специфичности. Это означает, что нет смысла квалифицировать идентификатор с классом или тегом (поскольку идентификатор уже является уникальным) или квалифицировать класс с тегом (поскольку класс должен быть более уникальным, чем тег, и если ваш цель состоит в том, чтобы класс выполнял две разные вещи в двух разных случаях, вы должны повысить удобочитаемость, сделав их двумя разными классами). Мне, однако, никогда не говорили, что использование классификатора класса на классе - это плохая практика (на самом деле я подозреваю, что Bootstrap использует их достаточно широко, основываясь исключительно на синтаксисе).
Эта статья из MDN, которая является одним из лучших результатов поиска для "css tag qualifying", похоже, согласна с моей точкой зрения, по крайней мере, если это плохая практика:
Если правило имеет селектор идентификаторов в качестве его селектора ключей, не добавляйте имя тега в правило. Поскольку идентификаторы уникальны, добавление имени тега будет бесполезно замедлять процесс сопоставления.
Далее говорится:
Предыдущая концепция также применяется [для определения тега с классом]. Хотя классы могут использоваться много раз на одной странице, они по-прежнему более уникальны, чем тег. Одним из условий, которые вы можете использовать, является включение имени тега в имя класса. Однако это может стоить некоторой гибкости; если в тег внесены изменения в конструкцию, имена классов также должны быть изменены. (Лучше всего выбирать строго семантические имена, поскольку такая гибкость является одной из целей отдельных таблиц стилей.)
CSS-трюки, похоже, согласны, говоря:
Идентификаторы уникальны, поэтому им не требуется имя тега, чтобы идти вместе с ним. Это делает селектор менее эффективным. Не делайте этого с именами классов, если вы можете избежать этого. Классы не уникальны, поэтому теоретически вы можете иметь имя класса, которое может быть полезно для нескольких разных элементов. И если вы хотите, чтобы этот стиль был другим, в зависимости от элемента, вам может потребоваться tag-qualify (например, li.first), но это довольно редко, так что вообще не делайте этого.
Я надеюсь, что это поможет ответить на ваш вопрос.
Ответ 2
Вам следует избегать вложенности, что сводит к минимуму вероятность столкновения других правил друг с другом. Убедитесь, что наши CSS-модули будут выглядеть одинаково в любом контексте.
.block__elem - синтаксис модификатора не уродлив, если вы не используете несколько вложенных элементов.
Ответ 3
Принцип BEM заключается в том, чтобы удалить всю фактическую иерархию в документе CSS и иметь только одно явное правило для каждого элемента, который должен быть стилизован. Вот почему он эффективен - рендерингу никогда не приходится проходить через DOM для решения правил для детей или пытаться сопоставить более чем с одним квалификатором (поэтому использование разделителя тегов рядом с селектором классов считается "плохим",). Но я согласен, стандартное соглашение об именах для BEM очень устарело. Вы можете изменить это в соответствии с вашими предпочтениями.
Вам нужно понять, что правила CSS обрабатываются справа налево. Пример:
.carousel-item {
header {…}
h2 {…}
footer {…}
}
Это приведет к тому, что рендеринг будет соответствовать всем элементам <header>
, <h2>
и <footer>
. С помощью этих совпадений он попытается найти подходящий родительский .carousel-item
, итерации до корня документа до тех пор, пока он не найдет его. Применение этого стиля к глубоко вложенному документу с несколькими элементами <h2>
и <header>
, не содержащимися в .carousel-item
, означало бы наличие много потерянных поисков. Проще говоря: это не очень эффективно.
Вы можете смягчить эффект, который это имеет, используя прямой дочерний селектор ( > ), так как тогда он не будет пытаться итерации полностью через DOM; он попробует только первого родителя. BEM избегает этой проблемы вообще.
Реально говоря, это очень незначительная проблема в наши дни, и больше циклов процессора, вероятно, потрачено на работу с клиентским JavaScript, чем неоптимальный CSS. Но хорошо иметь в виду, если вы собираетесь построить что-то большое.