Что такое БЭМ и как я использую его в WordPress

BEM (БЭМ — Block, Element, Modifier) — это методология организации компонентов интерфейса и CSS-классов. Её цель — сделать стили более предсказуемыми, масштабируемыми и менее зависимыми от конкретной структуры страницы.
Основная идея строится вокруг трёх понятий.
Block — самостоятельный компонент интерфейса.
Например, карточка товара:
<article class="card">
...
</article>
.card {
padding: 24px;
}
Такой блок не зависит от места использования. Одна и та же карточка может находиться в каталоге, на главной странице или в блоке рекомендаций.
Element — часть блока, которая не имеет самостоятельного смысла вне него.
<article class="card">
<h2 class="card__title">Название товара</h2>
<p class="card__text">Описание товара</p>
<a class="card__link" href="#">Подробнее</a>
</article>
Здесь card__title, card__text и card__link принадлежат блоку card. Двойное подчёркивание показывает эту связь.
Modifier — вариант или состояние блока либо элемента.
<article class="card card--featured">
.card--featured {
border: 2px solid;
}
Два дефиса обозначают модификатор.
При этом BEM — это не только формат записи классов. Важная идея методологии — независимость компонентов. Например, вместо зависимости от структуры страницы:
.catalog .card .card__title {
...
}
лучше держать стили самого компонента:
.card__title {
...
}
Тогда карточка остаётся самостоятельным компонентом и может использоваться в разных местах проекта.
При этом BEM не требует создавать класс для каждого HTML-элемента и описывать всю вложенность. Цель не в том, чтобы получить максимально подробную структуру, а в том, чтобы сохранить понятные границы компонентов.
И ещё важная мысль: конкретные разделители — двойное подчёркивание и два дефиса — это лишь договорённость. Её можно менять, и в разных проектах я использую разные варианты записи. Что при этом остаётся неизменным — покажу ниже.
Когда проект небольшой, организация CSS обычно не вызывает особых вопросов. Можно дать элементу класс, написать для него несколько правил и двигаться дальше. Проблемы начинаются позже, когда компонентов становится много, одни из них переиспользуются, а изменения в одном месте неожиданно затрагивают другое.
В какой-то момент я начал всё чаще использовать в проектах подход, похожий на БЭМ (BEM — Block, Element, Modifier): отдельные блоки, элементы внутри них и модификаторы для вариантов. При этом я никогда не пытался следовать методологии буквально. Мне были нужны прежде всего понятные границы компонентов и предсказуемые CSS-классы.
Недавно я решил разобраться, насколько этот подход вообще соответствует BEM и что из самой методологии действительно имеет смысл использовать сейчас — особенно в кастомных WordPress-проектах с ACF и Gutenberg.
Почему вообще понадобился BEM
В начале проекта я могу довольно свободно называть классы: .title, .button, .item, .content. Пока компонентов немного, это работает. Но по мере роста проекта такие названия становятся слишком общими.
Например, .title может оказаться заголовком карточки, секции, модального окна или блока с преимуществами. Можно добавлять контекст к селекторам:
.catalog .card .title {
...
}
но вместе с этим CSS начинает зависеть от конкретной структуры HTML. Если тот же компонент понадобится в другом месте, его стили приходится либо дублировать, либо учитывать ещё один вариант вложенности.
Именно эту проблему я и пытался решить с помощью BEM. Не столько придумать красивую систему названий, сколько сделать компоненты более независимыми друг от друга.
Что именно беру из BEM
Для меня основная ценность BEM оказалась не в конкретной записи вроде block__element--modifier, а в разделении ролей: есть блок, есть его части и есть модификаторы для вариантов.
Саму нотацию я при этом считаю переменной величиной. Она может отличаться от проекта к проекту, и это нормально, пока сохраняются роли классов. На практике у меня встречаются два варианта записи, и оба для меня рабочие.
Канонический. Часть блока пишется через двойное подчёркивание, модификатор — через два дефиса:
<article class="card">
<h3 class="card__title">Деревянный стол</h3>
<p class="card__price">85 000 ₽</p>
</article>
<article class="card card--featured">
Упрощённый. Часть блока пишется через один дефис, а два дефиса остаются только за модификатором:
<article class="card">
<h3 class="card-title">Деревянный стол</h3>
<p class="card-price">85 000 ₽</p>
</article>
<article class="card card--featured">
Смысл в обоих случаях один. И card__title, и card-title читаются как «заголовок внутри карточки», а card--featured — как «вариант карточки». Разница только в разделителе, а роли блок, элемент и модификатор сохраняются.
Но ещё важнее другое правило BEM — блок по возможности не должен зависеть от места, в котором он используется. Если .card находится внутри .catalog, я не обязан писать .catalog .card. Карточка остаётся самостоятельным компонентом и может использоваться в другом разделе без изменения её базовых стилей.
Именно эта независимость для меня полезнее самого синтаксиса с двойным подчёркиванием и двумя дефисами.
Где не следую БЭМ буквально
При этом я не пытаюсь соблюдать BEM буквально. Например, мне не кажется полезным превращать каждый HTML-элемент в отдельный BEM-элемент только ради соответствия методологии.
Если внутри карточки есть заголовок, цена и кнопка, мне достаточно классов для тех частей, которые действительно участвуют в стилизации или поведении компонента. При этом кнопку можно решить двумя способами.
Если она переиспользуется в разных блоках, логично сделать её самостоятельным компонентом и не привязывать к карточке:
<article class="card">
<h3 class="card__title">Деревянный стол</h3>
<p class="card__price">85 000 ₽</p>
<a class="button" href="#">Подробнее</a>
</article>
А если кнопка существует только внутри этого блока и нигде больше не повторяется, её логичнее назвать его частью — card__button или card-button. Плохого варианта здесь нет: важно один раз решить, чем кнопка является, и не смешивать оба подхода в одном проекте.
По той же причине я стараюсь не строить длинных цепочек вроде card__content__title или card-content-title: часть принадлежит блоку напрямую, поэтому достаточно card__title или card-title. Чем длиннее имя, тем сложнее понять, где заканчивается имя блока и начинается имя элемента.
Для меня это важнее формального соблюдения синтаксиса. Если правило помогает определить границы компонента — я его использую. Если оно только увеличивает количество классов и усложняет разметку, смысла в таком использовании BEM я не вижу.
Почему независимость блоков важнее названий классов
Если воспринимать BEM только как соглашение о названиях классов, его польза действительно кажется довольно ограниченной. Для меня важнее другое — возможность рассматривать компонент независимо от места, где он находится.
Например, карточка товара может использоваться в каталоге, на главной странице и в блоке рекомендаций. Я не хочу, чтобы её внешний вид зависел от каждого из этих контейнеров.
Поэтому вместо такого селектора:
.catalog .products .card .card__title {
...
}
я стараюсь держать стили самого компонента на его уровне:
.card__title {
...
}
При упрощённой записи то же самое выглядит как .card-title без внешних селекторов — суть не меняется.
Полностью отказаться от контекста на практике не получается: один и тот же блок в разных местах может требовать другой ширины или отступов. Но в таком случае контекст задаёт расположение, а не внешний вид самого компонента, и остаётся осознанным исключением, а не основным способом построения CSS.
Есть и отдельный случай — большие сайты с множеством непохожих страниц. Если страница собирается из собственных блоков, которые больше нигде не встречаются, их стили можно вынести в отдельный файл и подключать только на этой странице. Формально это тоже привязка к месту, но касается она не оформления общего компонента, а загрузки ресурсов: неиспользуемый CSS просто не попадает на остальные страницы. Для меня такой компромисс оправдан, если у этих блоков есть свои осмысленные имена, а не переопределения общих классов через контекст.
В кастомном WordPress это особенно удобно. ACF-блок может быть выведен в нескольких шаблонах или секциях страницы, а его стили при этом остаются привязанными к самому компоненту, а не к конкретному месту вывода.
Получается более предсказуемая система: шаблон отвечает за расположение блоков, а сам блок — за собственное оформление и поведение.
Когда BEM начинает создавать лишнюю работу
У BEM есть обратная сторона: если воспринимать его как набор правил, которые нужно соблюдать любой ценой, разметка быстро становится перегруженной.
Например, можно дойти до ситуации, когда для каждого небольшого элемента появляются собственные классы:
<div class="card">
<div class="card__content">
<h3 class="card__content__title">Название</h3>
<div class="card__content__meta">
<span class="card__content__meta__price">85 000 ₽</span>
</div>
</div>
</div>
Формально это может выглядеть как попытка подробно описать структуру компонента, но практически такая схема только усложняет код. Особенно если HTML потом изменится.
Я предпочитаю более плоскую структуру:
<div class="card">
<div class="card__content">
<h3 class="card__title">Название</h3>
<div class="card__meta">
<span class="card__price">85 000 ₽</span>
</div>
</div>
</div>
Здесь классы описывают не всю DOM-иерархию, а смысловые части компонента. Имя card__content остаётся у обёртки, но заголовок и цена не наследуют его целиком в своём названии.
Поэтому для себя я использую BEM скорее как ограничение зависимости между компонентами, чем как требование дать имя каждому элементу. Если изменение HTML приводит к необходимости переименовать половину CSS-классов, такая структура, скорее всего, слишком тесная и хрупкая.
Как организую компоненты в проекте
На практике я стараюсь мыслить не отдельными HTML-элементами, а компонентами интерфейса. Например, секция с преимуществами для меня является самостоятельным блоком, внутри которого есть только необходимые элементы.
В упрощённой записи у неё может быть такой набор классов:
advantages
advantages-item
advantages-title
advantages-text
В канонической записи те же части называются так:
advantages
advantages__item
advantages__title
advantages__text
Если появляется альтернативный вариант блока, добавляется модификатор — одинаковый в обеих записях:
advantages
advantages--compact
При этом я не привязываю классы к конкретной странице. Мне не нужен отдельный вариант вроде .home-advantages только потому, что сейчас блок используется на главной.
В PHP-шаблоне ACF-блока это выглядит примерно так же просто (ниже — упрощённая запись, при канонической классы будут advantages__item и так далее):
<section class="advantages">
<?php while (have_rows('items')) : the_row(); ?>
<div class="advantages-item">
<h3 class="advantages-title">
<?php the_sub_field('title'); ?>
</h3>
<p class="advantages-text">
<?php the_sub_field('text'); ?>
</p>
</div>
<?php endwhile; ?>
</section>
BEM не обязан описывать весь CSS
Со временем я пришёл к тому, что не стоит пытаться подогнать под BEM абсолютно всё. В проекте всё равно есть глобальные стили, типографика, сетка, служебные классы и состояния, которые не обязательно являются элементами конкретного блока.
Например, я могу отдельно задать общие правила для заголовков или контейнера:
.container {
width: min(100% - 40px, 1200px);
margin-inline: auto;
}
А компонент при этом остаётся самостоятельным:
.card {
padding: 24px;
}
.card__title {
margin: 0;
}
Мне не нужно превращать .container в элемент какого-нибудь блока только потому, что он используется рядом с ним.
То же самое относится к состояниям. Например, .open или .active (а в канонической записи — .is-open, .is-active) могут быть служебными классами, которые описывают состояние элемента, а не его принадлежность к BEM-блоку. Такие классы добавляются и снимаются скриптом, поэтому держать их отдельно от структуры удобнее.
Поэтому в реальном проекте у меня получается не «чистый BEM», а комбинация нескольких уровней: компоненты имеют собственные классы, глобальные стили остаются глобальными, а служебные классы решают свои задачи. BEM в этой системе отвечает прежде всего за структуру компонентов и их независимость.
Нужен ли BEM сегодня
После всего этого у меня не возникает желания отказаться от BEM только потому, что появились новые подходы к организации CSS. Да, современные инструменты позволяют решать часть тех же проблем другими способами: CSS Modules изолируют классы на уровне сборки, CSS-in-JS связывает стили с компонентами, а компонентные фреймворки задают собственную архитектуру интерфейса.
Но в кастомном WordPress-проекте мне не всегда нужны такие инструменты. Если проект строится на обычном HTML, PHP, CSS и небольшом количестве JavaScript, BEM остаётся достаточно простым способом договориться с самим собой о структуре классов.
Мне не нужно добавлять сборщик только ради изоляции CSS или внедрять отдельную архитектуру компонентов там, где её можно получить более простым способом.
Поэтому я бы не говорил, что BEM устарел. Скорее, его уже не стоит воспринимать как обязательную методологию для любого веб-проекта. Для обычной кастомной WordPress-разработки это по-прежнему практичный инструмент — при условии, что использовать его без фанатизма.
Что в итоге остаётся от BEM в моей работе
Сейчас я воспринимаю BEM не как набор правил, которые нужно выполнить при вёрстке, а как способ поддерживать порядок в CSS.
Я использую понятие блока, чтобы обозначить самостоятельный компонент, элементы — чтобы связать его внутренние части, а модификаторы — когда у компонента появляется отдельный вариант. При этом не пытаюсь описать классами всю DOM-структуру и не привязываю компоненты к конкретным страницам.
А конкретная запись может отличаться от проекта к проекту: где-то block__element--modifier и состояния вида .is-open, где-то упрощённый вариант через один дефис и .open. Для меня это второстепенно. Важнее, что блок остаётся самостоятельным компонентом, а его части и варианты обозначены предсказуемо и единообразно внутри проекта.
Для кастомного WordPress этого мне обычно достаточно. ACF отвечает за редактирование и структуру контента, WordPress — за саму систему блоков, а BEM помогает организовать собственные компоненты и их стили.
Поэтому я продолжаю его использовать, но скорее как практический набор принципов, чем как методологию, которой необходимо следовать буквально.