Почему CSS-модули не могут заменить БЭМ

Часто слышу, как разработчики говорят «БЭМ не нужен, ведь есть CSS-модули». Это не так.

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

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

Эволюция выглядит так:

/* Классический БЭМ с длинными именами классов для обеспечения изоляции */

.shop-cart-button {}
.shop-cart-button_size_small {}
.shop-cart-button_size_large {}


/* CSS-модули с неограниченной свободой творчества в именах классов */

.button {}
.small {}
.large {}
/* или */
.button {}
.is-small {}
.is-large {}
/* или */
.button {}
.size-small {}
.size-large {}


/* БЭМ и CSS-модули */

.button {}
.button_size_small {}
.button_size_large {}

Сразу отвечу на вопрос «а чем плох пример с классами .button, .small и .large?». Он плох тем, что классы .small и .large сами по себе не несут информации о том, к чему они относятся. Нельзя понять, стилизуют ли они отдельный элемент или описывают состояние существующего элемента. Также такие названия классов рано или поздно снова приведут вас к проблеме уникальности имён. Например, вы пишете стили для модального окна. Вам нужно стилизовать полупрозрачный оверлей поверх страницы и само модальное окно. Оба этих элемента могут быть в двух состояниях: виден или скрыт. Кажется, что класс .visible отлично подходит, но проблема в том, что для оверлея и для окна этот класс должен содержать разные стили. Можно придумать костыль в виде селекторов .overlay.visible и .window.visible, но это именно костыль, потому что вы увеличиваете специфичность. С БЭМом всё просто и без ненужного роста специфичности: .overlay_visible и .window_visible.

Share
Send
4 comments
Roman Holovin

Это интересное мнение, но вы забываете самую главную фичу модулей – composes.

Выглядит это как-то так:

.button { общие стили для всех кнопок, этот класс не используется напрямую в верстке}
.small { стили для мелкой кнопки}
.large { стили для большой кнопки}

.button--regular {
composes: button;
+если надо
}

.button--small {
composes: button;
composes: small;
}

.button--large {
composes: button;
composes: large;
}

Класс button не должен использоваться в верстке напрямую, нужно использовать button--regular, button-small или button-large.

Это лучшее из двух миров вместе. CSS модули убедятся в том, что если вы создатите 2 одинаковых по названию но разных по стилю компонента кнопки, они не пересекутся и не помешают друг другу.

Roman Holovin

Ну и распостранненая ошибка, которую я на всякий случай, тут распишу, может читателям пригодится.

Вообще, имя класса button--small не очень хорошая практика. Если просто общий компонент, и этот класс никогда не будет напрямую использован в верстке – то ок.

А если использовать его нарямую то может возникнуть проблема, чтоэто у вас он сейчас в текущем дизайне маленькая, а завтра станет большая, переименовывать из-за этого классы – дело неблагодарное. Если это модуль сайта “shopping cart” и там есть кнопка – “checkout” (оформить заказ), то, мне кажется, что правильнее будет назвать класс “checkout-button” и стили сделать

.checkout-button {
composes: button-small;
}

завтра поменяете на

.checkout-button {
composes: button-large;
}

и все, готово.

Андрей Романов

Хорошее уточнение, как раз недавно читал статью об этой проблеме. Всем советую, там подробно описан этот подход — http://www.lispcast.com/cascading-separation-abstraction

Мимопроходил

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

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

Андрей, перечитай пожалуйста свою статью и скажи кому и о чём ты написал? Кто и что должен сделать или решить после твоей статьи.

Андрей Романов

Ребята, строительство стадионов это не теоретическая физика, реальным людям нужны реальные стадионы! Вы на полном серьёзе думаете, что когда куча строителей по-быстрому чинят протекающую крышу, чтобы начальство по шапке не надавало, то в этот момент они размышляют о том, как хорошо было бы изначально всё сделать по уму?

Павел

На дворе 2017, а ощущение, что вы до сих пор не понимаете бэм (ту ее часть, что про именование классов).

Сравниваете .shop-cart-button в бэм и .button в модулях. В бэм, это будет точно такой же .button, с дополнительным классом, определяющим принадлежность кнопки к блоку, например .button.shop-cart__button Если же речь идет о кнопке, которая не имеет ничего общего с обычными кнопками на сайте (.button), тогда вообще можно будет обойтись только классом элемента .shop-cart__button

Что же касается примера с модулями, то там просто не указывается принадлежность кнопки к какому-либо блоку (что не совсем честно).

Ну и на выходе, получили чистой воды бэм, без всяких модулей.

По моему мнению, статья, скорее вводит в заблуждение, чем проясняет картину. Толком о преимуществах и недостатках подходов ничего не сказано. Примеры приведены сомнительные. Автор объединил Неправильный бэм и модули, получил правильный бэм. Халтура.

Your comment
won’t be published

HTML will not work

Ctrl + Enter
Popular