Начнем с терминов.

Классы (class) - это механизм, позволяющий задавать одно и то же свойство стиля для нескольких элементов веб-страницы.

Идентификаторы (id) - атрибут id указывает уникальный идентификатор для элемента HTML (значение должно быть уникальным в HTML-документе).

БЭМ - это методология разработки веб-интерфейсов, которая помогает структурировать и организовывать код HTML и CSS. Она основана на трех основных концепциях: блок, элемент, модификатор.

HTML (HyperText Markup Language) - это язык разметки, используемый для создания структуры и содержания веб-страниц. Одним из важных аспектов в HTML является возможность задавать элементам и компонентам уникальные имена с помощью классов и идентификаторов. В этой статье мы рассмотрим, зачем они нужны, когда их использовать, и как работает методология БЭМ (Блок, Элемент, Модификатор).

Зачем нужны классы и идентификаторы

Классы и идентификаторы позволяют уникально идентифицировать элементы и компоненты на веб-странице. Идентификаторы (задаются через атрибут id) являются уникальными для всей страницы, тогда как классы (задаются через атрибут class) могут быть применены к нескольким элементам.

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

Классы и идентификаторы часто используются в JavaScript для обращения к элементам страницы и добавления им динамического поведения. Например, скрипты могут изменять классы элементов, основываясь на событиях или действиях пользователя.

Когда использовать классы и идентификаторы

Идентификаторы (id) должны использоваться, когда нужно уникально идентифицировать элемент на странице. Например, идентификатор может быть использован для якорей внутри документа.

Классы (class) применяются, когда нужно группировать несколько элементов с общими характеристиками или стилями. Классы могут быть использованы на нескольких элементах.

Методология БЭМ (Блок, Элемент, Модификатор)

Блок представляет собой компонент страницы, который может содержать другие элементы или модификаторы. Например, блок "button" может содержать текст и иконку.

<div class="button">
  Кнопка
</div>

Элементы находятся внутри блока и представляют собой его составные части. Они именуются с использованием двойного подчеркивания __.

<div class="button">
  <span class="button__text">
    Кнопка
  </span>
</div>

Множественные элементы блока, например, элементы списка могут быть названы как -item:

<ul class="cards__container">
  <li class="cards__container-item">
    Элемент 1
  </li>
  <li class="cards__container-item">
    Элемент 2
  </li>
  <li class="cards__container-item">
    Элемент 3
  </li>
</ul>

Модификаторы используются для изменения внешнего вида или поведения блока или элемента. Они именуются с использованием одинарного подчеркивания _.

<div class="button button_primary">
  Кнопка
</div>

Обращение к классам и идентификаторам из CSS

Чтобы применить стили к классам или идентификаторам, вы можете использовать селекторы. Например, чтобы стилизовать элемент с классом "button", вы можете написать:

.button {
  background-color: #007bff;
  color: #fff;
}

Из JavaScript вы можете получить доступ к элементам по их классам или идентификаторам с использованием методов, таких как document.querySelector() или document.getElementById().

Пример обращения из JavaScript к элементу по классу:

const buttonElement = document.querySelector('.button');

Перейдем к примерам. Допустим, что согласно дизайн-макету у вас есть 3 прямоугольных блока с определенными размерами и цветом фона. Однако, последний элемент из данного списка имеет отличный от двух других фоновый цвет:

Стоит начать с изучения макета. Мы видим, что у всех трех элементов заданы одинаковые размеры и у двух элементов из трех одинаковый цвет фона. Предположим, что и у третьего элемента изначально был красный цвет фона. Исходя из анализа макета, все три элемента можно классифицировать и задать общие стили:

Задав для всех трех div класс "cards__container-item" и обратившись по данному селектору в CSS мы объявили общие стили для всех трех элементов. Внимание: задав для трех HTML-элементов одинаковый класс - в CSS нам стоит только один раз прописать сценарий для данного селектора. Это будет выглядеть так:

<div class="cards__container-item"></div>
<div class="cards__container-item"></div>
<div class="cards__container-item"></div>
.cards__container-item{
  width: 263px;
  height: 393px;
  background: red;
}


Теперь нам необходимо выделить последний блок из данного списка. Здесь мы прибегнем к модификатору. Запомните: классы в HTML в атрибуте class перечисляются через пробел!

Мы добавили дополнительный класс-модификатор "cards__container-item_blue" к элементу "cards__container-item", который указывает на внешний вид данного элемента. Обратите внимание, что в CSS создан отдельный сценарий и свойство для нового селектора под предыдущим сценарием. Это сделано для переопределения свойства "background". Если бы мы в атрибуте class у HTML-элемента написали бы класс-модификатор, а за ним класс элемента, а в CSS сначала объявили сценарий для модификатора, а затем для элемента, то нужный нам элемент имел бы красный фон, так как очередность классов в HTML и CSS имеет важную роль.

Чем ниже селектор в CSS - тем данный сценарий приоритетнее!

Приоритет элементов

В HTML приоритет классов определяет, какие стили будут применены к элементу, если один и тот же элемент имеет несколько классов, и каждый из них задает свои стили. Приоритет классов определяется по их специфичности и порядку в файле стилей (CSS). Давайте рассмотрим приоритет классов более подробно:

  1. Специфичность (Specificity): Это основной фактор определения приоритета классов в CSS. Каждому селектору присваивается числовое значение специфичности, и чем оно выше, тем выше приоритет. Специфичность определяется следующим образом:

  2. Идентификатор (ID): Селектор с ID имеет более высокий приоритет и получает 100 баллов специфичности.

  3. Классы и псевдоклассы: Селекторы с классами, псевдоклассами и атрибутами имеют средний приоритет и определяются исходя из количества совпадающих классов и псевдоклассов.

  4. Теги и псевдоэлементы: Селекторы с тегами и псевдоэлементами имеют наименьший приоритет.

Примеры специфичности:

  1. #header (100 баллов) более специфичен, чем .navbar (10 баллов).

  2. .sidebar a (20 баллов) более специфичен, чем p (1 балл).

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

Пример:

.button {
  background-color: red; /* Первое вхождение */
}
.button {
  background-color: blue; /* Последнее вхождение, переопределяет
                             предыдущее значение */
}

В данном случае кнопка будет иметь фон синего цвета, потому что второе правило переопределяет первое.

  1. Важность (Importance): Можно задать важность для стилей, используя ключевое слово !important. Если стиль имеет важность, он будет иметь самый высокий приоритет и переопределит любые другие стили, даже если они более специфичны или определены позднее.

Пример:

.button {
  background-color: red !important; /* Самый высокий приоритет */
}
.button {
  background-color: blue;
}

Кнопка будет иметь фон красного цвета, даже если другой стиль определен последним.

Итак, приоритет классов в HTML определяется специфичностью селекторов, порядком в файле стилей и важностью. В большинстве случаев рекомендуется избегать использования !important, так как он может делать код менее читаемым и поддерживаемым. Вместо этого старайтесь следовать лучшим практикам и организовывать стили ваших классов так, чтобы избежать конфликтов и создавать читаемый и легко поддерживаемый CSS.

Итог

Классы и идентификаторы в HTML и CSS - это мощные инструменты для структурирования и стилизации веб-страниц. Вот ключевые моменты, которые стоит запомнить:

  1. Цель использования: Классы и идентификаторы предназначены для добавления структуры и стилей в HTML-документ. Классы используются для определения множества элементов с общими характеристиками, в то время как идентификаторы уникальны для каждого элемента.

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

  3. Использование идентификаторов: Идентификаторы (через атрибут id) применяются, когда нужно обратиться к конкретному уникальному элементу на странице. Они имеют более высокий приоритет и могут использоваться для навигации и скриптов.

  4. Методология БЭМ: БЭМ (Блок, Элемент, Модификатор) - это методология именования классов, которая помогает создавать понятный и легко поддерживаемый код. Блок представляет собой независимый компонент, элемент - часть блока, а модификатор - его измененное состояние.

  5. Пример БЭМ: Например, для создания стилизованных кнопок с БЭМ, вы можете использовать классы вроде button (блок), button__label (элемент) и button_primary (модификатор).

  6. Обращение из CSS: Для обращения к классам и идентификаторам из CSS, используйте соответствующие селекторы. Классы указываются с точкой (например, .button), а идентификаторы с решеткой (например, #header).

  7. Осторожно с идентификаторами: Используйте идентификаторы осторожно и только тогда, когда это необходимо, чтобы избежать конфликтов и обеспечить читаемость кода.

В заключение, правильное использование классов и идентификаторов в HTML и CSS может значительно упростить создание и поддержку веб-страниц, делая код более читаемым и управляемым. Методология БЭМ помогает организовать именование классов для лучшей структурированности проекта.

Комментарии (12)


  1. delphinpro
    12.10.2023 17:39
    +2

    Множественные элементы блока, например, элементы списка могут быть названы как -item:

    Здесь может сложиться неправильное впечатление, что необходимо использовать все дерево имен блока. Запись .cards__container-item в принципе допустима, если рассматривать часть "container-item" как единое целое, а не "-item" как продолжение "cards__container". В данном конкретном примере было бы лучше дать элементам списка класс .cards__item, а для иллюстрации двух-, трехсложных имен придумать что-то другое.

    класс-модификатор "cards__container-item_blue"

    В классическом БЭМ различают булевы модификаторы и модификаторы со значением. Здесь опять же следует применить модификатор со значением (цветов может быть много) – .cards__container-item_color_blue. В качестве примера булева модификатора можно например привести .button_disabled


    1. starijdmitry Автор
      12.10.2023 17:39

      Согласен с Вами. Однако данный пример был продемонстрирован для примера нэйминга классов.


  1. nin-jin
    12.10.2023 17:39
    +2

    БЭМ был актуален лет 10 назад, когда верстальщики ещё не умели в компонентную декомпозицию, а верстали всю страницу целиком с нуля, а потому имели возможность просунуть элемент-класс на любую глубину. Но сейчас даже войтивайти собирают интерфейс из компонент, из-за чего нет возможности просунуть элемент-класс на более чем 1 уровень глубины, что делает БЭМ нежизнеспособным. Чтобы его починить, надо вводить "фрактальные блоки", классы которых собираются в рантайме на основе последовательности имён от корня, как это сделано, например, в $mol.


    1. starijdmitry Автор
      12.10.2023 17:39

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


    1. ILaeeeee
      12.10.2023 17:39
      +2

      Компоненты? Вы предлагаете все сайты на JS верстать? Мне кажеться, это перебор.


    1. Spaceoddity
      12.10.2023 17:39
      +1

      И получают на выходе такую кашу... То, что вы лепите интерфейсы через компонентный подход - это отрадно. CSS тут при чём? И "уровень глубины"? БЭМ как раз специально отходит от концепций каскада и специфичности - нужен просто уникальный класс для каждой сущности. Ну и компоненты компонентами, но как вы их в итоге на странице размещать собрались? Глобальные стили тоже отдельным компонентом прописываете?))


  1. alex_k777
    12.10.2023 17:39
    +1

    cards__container-item некрасиво выглядит, лучше cards__item для элемента списка, а список как отдельный блок cards


    1. starijdmitry Автор
      12.10.2023 17:39

      Да, как ответил выше - это для примера нейминга. Ваш вариант тоже верный!


  1. Sayneone
    12.10.2023 17:39
    +1

    Дим, вы молодец! Так держать!


    1. starijdmitry Автор
      12.10.2023 17:39

      Благодарю!!!


  1. danilovmy
    12.10.2023 17:39
    +1

    Я сейчас такую тупую вещь спрошу. А зачем может понадобиться так сложно работать с классами?

    Например, есть у вас много UL в них много LI. Поставил на <UL class="card"> и выбирай все первые LI: ul.card > li

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

    Кстати, по примерам видно, что речь скорее идет про ABEM, потому как в настоящем BEM модификаторы идут через "--". Пруф.

    Спасибо, за статью, за четыре года знакомства и попыток пользоваться этой методологией, я все еще не прочувствовал, какое удобство добавляет БЭМ? Сeйчас у меня в проекте около 230 компонентов, в них применены bootstrap и, позже, tailwind и я так и не осознал, что бы мне дал переезд на BEM или ABEM.


    1. starijdmitry Автор
      12.10.2023 17:39

      Не вижу ничего сложного в данном подходе)
      В своих работах я крайне редко обращаюсь по тэгам. Я предпочитаю, чтобы элементы были классифицированы для более удобной работы с ними. С глубокой вложенностью, например, с использованием препроцессоров данная штука очень удобна.
      В ABEM используется конструкция class="card -primary -large", что также отличается от продемонстрированных примеров.
      Я использовал примеры, какими пользуюсь ежедневно. Действительно, в БЭМ модификаторы обозначаются через "--", но некоторые сокращают данную запись до "_", что по мне так является более удобным вариантом.