Методология 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. Его сила — в последовательности, а не в жёстких правилах.
Рекомендации:
- Начните применять BEM с новых компонентов.
- Не стремитесь к «идеальному» BEM — стремитесь к последовательному.
- В React используйте BEM там, где он добавляет ценность: в UI-библиотеках, дизайн-системах, крупных проектах.
Главное — писать код, который легко читать не только вам сейчас, но и вашему коллеге (и вам) через год. BEM помогает в этом.