Методология BEM

1. Введение

1.1. Зачем нужны методологии в вёрстке?

При разработке крупных интерфейсов без чёткой структуры CSS быстро превращается в «спагетти»: селекторы конфликтуют, стили влияют на непреднамеренные элементы, а изменение одного компонента ломает другие. Особенно остро это ощущается в командной работе и при масштабировании проекта.

Методологии, такие как BEM, решают эти проблемы за счёт:

  • явного разделения ответственности между компонентами,
  • предсказуемой структуры классов,
  • изоляции стилей.

1.2. Краткая история BEM

BEM (Block – Element – Modifier) была разработана в Яндексе около 2010 года для решения задач масштабируемости больших веб-интерфейсов. Основная идея — строить UI из независимых, переиспользуемых блоков, которые не зависят от контекста размещения.


2. Основные понятия BEM

2.1. Блок (Block)

Блок — это автономный компонент интерфейса, который может существовать независимо.
Примеры: Button, Header, ProductCard.

Важно:

  • Блок не знает о других блоках.
  • Может быть переиспользован в любом месте без изменений стилей.

2.2. Элемент (Element)

Элемент — часть блока, не имеющая смысла вне него.
Пример: у блока ProductCard могут быть элементы __image, __title, __price.

Правило:

  • Элемент всегда принадлежит конкретному блоку.
  • Нельзя использовать элемент без родительского блока.

2.3. Модификатор (Modifier)

Модификатор — это флаг, описывающий состояние или вариант внешнего вида блока/элемента.
Примеры: button--primary, menu__item--active.

Важно:

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

3. Правила именования

3.1. Синтаксис классов

  • Блок: .block
  • Элемент: .block__element
  • Модификатор блока: .block--modifier
  • Модификатор элемента: .block__element--modifier

3.2. Рекомендации

  • Используйте осмысленные английские имена (search-form, а не sfrm).
  • Не используйте теги, ID или глобальные селекторы в связке с BEM.
  • Избегайте вложенности в селекторах — каждый класс должен быть самодостаточным.

3.3. Примеры

Корректно:

<div className="card card--highlighted">
  <h2 className="card__title">Title</h2>
</div>

Некорректно:

// Элемент вне блока
<span className="title">Title</span>

// Модификатор без базового класса
<div className="card--highlighted">...</div>

// Вложенность элементов
<div className="card__header__logo">...</div>

4. Преимущества BEM

  • Читаемость: по имени класса сразу ясно, к какому блоку он относится.
  • Изоляция: стили одного блока не влияют на другие.
  • Поддержка: легко вносить изменения без страха сломать что-то в другом месте.
  • Командная работа: единые правила упрощают код-ревью и onboarding.

5. Практические примеры в React

5.1. Простой компонент: кнопка

// Button.jsx
export default function Button({ variant = 'default', children, disabled = false }) {
  const baseClass = 'button';
  const modifierClass = variant ? `button--${variant}` : '';
  const disabledClass = disabled ? 'button--disabled' : '';

  return (
    <button className={[baseClass, modifierClass, disabledClass].filter(Boolean).join(' ')}>
      {children}
    </button>
  );
}
/* Button.css */
.button {
  padding: 8px 16px;
  border: 1px solid #ccc;
  background: white;
}

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

.button--disabled {
  opacity: 0.6;
  pointer-events: none;
}

5.2. Сложный компонент: карточка товара

// ProductCard.jsx
export default function ProductCard({ title, price, isFeatured, hasDiscount }) {
  return (
    <article className={`product-card ${isFeatured ? 'product-card--featured' : ''}`}>
      <img className="product-card__image" src="..." alt={title} />
      <h3 className="product-card__title">{title}</h3>
      <span className={`product-card__price ${hasDiscount ? 'product-card__price--discounted' : ''}`}>
        ${price}
      </span>
    </article>
  );
}
.product-card {
  border: 1px solid #eee;
  padding: 16px;
}

.product-card--featured {
  border-color: gold;
  box-shadow: 0 0 8px rgba(255, 215, 0, 0.3);
}

.product-card__title {
  font-size: 1.2rem;
  margin: 8px 0;
}

.product-card__price--discounted {
  color: red;
  text-decoration: line-through;
}

6. Распространённые ошибки

Ошибка Почему плохо Как исправить
block__elem1__elem2 Нарушает плоскую структуру Создать отдельный блок или пересмотреть архитектуру
Использование .block--mod без .block Стили не применяются корректно Всегда указывать базовый класс
Смешивание BEM с глобальными селекторами Ломает изоляцию Держать все стили внутри BEM-классов
Чрезмерное количество модификаторов Усложняет поддержку Выделить новый блок, если логика сильно отличается

7. Инструменты и экосистема

  • Sass/Less: можно использовать вложенность, но только для модификаторов и элементов внутри блока, например:

    .button {
      // базовые стили
    
      &--primary { /* ... */ }
      &__icon { /* ... */ }
    }
    

    Это не нарушает принципы BEM, если генерируемый CSS остаётся плоским.

  • Stylelint: настройте правила plugin/stylelint-bem для автоматической проверки именования.

  • CSS Modules: отлично сочетаются с BEM — вы получаете изоляцию на уровне сборки + семантику BEM.


8. BEM в современной разработке

8.1. BEM + CSS-in-JS

В CSS-in-JS (например, styled-components) BEM теряет актуальность, так как каждый компонент уже изолирован. Однако идеи BEM (блок/элемент/модификатор) полезны для внутренней структуры компонента.

Альтернатива: использовать объектную структуру стилей:

const styles = {
  button: { /* базовый */ },
  button_primary: { /* модификатор */ }
};

8.2. BEM в React-компонентах

BEM особенно эффективен в React, когда:

  • вы используете обычный CSS или CSS Modules,
  • компоненты рендерят много дочерних элементов,
  • важна читаемость HTML в DevTools.

Не нужно применять BEM к каждому <div> — только к тем компонентам, которые имеют визуальную или функциональную целостность.

8.3. Альтернативы

  • SMACSS: похож на BEM, но менее строгий.
  • Atomic CSS / Utility-first (Tailwind): вместо семантических имён — утилиты (p-4, bg-blue-500). Подходит для быстрой разработки, но хуже документирует бизнес-логику.
  • CSS Modules / Scoped CSS: решают проблему изоляции, но не дают соглашения по структуре.

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


9. Заключение

BEM — это не догма, а практический инструмент для организации CSS. Его сила — в последовательности, а не в жёстких правилах.

Рекомендации:

  1. Начните применять BEM с новых компонентов.
  2. Не стремитесь к «идеальному» BEM — стремитесь к последовательному.
  3. В React используйте BEM там, где он добавляет ценность: в UI-библиотеках, дизайн-системах, крупных проектах.

Главное — писать код, который легко читать не только вам сейчас, но и вашему коллеге (и вам) через год. BEM помогает в этом.