Утилитарный CSS и CSS-модули
БЭМ решает проблему общего пространства имён договорённостью: люди сами следят, чтобы имена не совпадали. Есть два других пути. Первый — почти не придумывать имён, собирая вид из готовых маленьких классов. Второй — поручить уникальность имён инструментам сборки.
Утилитарные классы
Утилита — класс, который делает одну вещь: задаёт отступ, цвет или скругление. Подход utility-first («сначала утилиты») собирает внешний вид прямо в разметке из таких классов:
<style>
.p-3 { padding: 12px; }
.rounded { border-radius: 8px; }
.border { border: 1px solid silver; }
.bg-light { background: whitesmoke; }
.bold { font-weight: bold; }
.text-green { color: seagreen; }
</style>
<div class="p-3 rounded border bg-light">
<div class="bold">Рюкзак</div>
<div class="text-green">40 €</div>
</div>В CSS нет ни одного правила про карточку — карточка получилась из сочетания утилит.
Tailwind
Самая известная библиотека утилит — Tailwind CSS. В ней тысячи готовых классов вроде p-4, bg-white, rounded-lg, hover:bg-gray-100, а в итоговый файл попадают только те, что встретились в разметке. Плюсы: не нужно придумывать имена, CSS почти не растёт, стили видны прямо в HTML. Минусы: длинные атрибуты class и необходимость выучить словарь классов.
CSS-модули
CSS-модули — функция сборщиков: программ, которые готовят код проекта к публикации. Вы пишете обычные короткие имена, а сборщик автоматически делает их уникальными, например .title превращается в .Card_title_x7f2:
/* Card.module.css содержит: .title { color: rebeccapurple; } */
import styles from './Card.module.css';
export function Card() {
return <h3 className={styles.title}>Рюкзак</h3>;
}Класс .title из этого файла никогда не столкнётся с .title другого компонента. Подход популярен в React-проектах.
Scoped-стили во фреймворках
JavaScript-фреймворки Vue, Svelte и Angular умеют ограничивать стили компонентом: правила из блока стилей действуют только на его разметку. Во Vue для этого есть атрибут scoped:
<template>
<h3 class="title">Рюкзак</h3>
</template>
<style scoped>
.title { color: rebeccapurple; }
</style>Конфликтов имён нет, а мёртвый CSS удаляется вместе с файлом компонента.
Что выбрать
| Ситуация | Подходящий подход |
|---|---|
| Обычный сайт без фреймворка | БЭМ, при желании с Sass и @layer |
| Быстрые прототипы, маленькая команда | утилиты или Tailwind |
| Проект на React | CSS-модули или Tailwind |
| Проект на Vue или Svelte | scoped-стили |
Подходы смешивают: компоненты по БЭМ или в модулях плюс десяток утилит вроде .visually-hidden. Главное — чтобы команда договорилась.
Частая ошибка
Копировать один и тот же длинный набор утилит в каждое место:
<style>
.px-3 { padding: 6px 12px; } .rounded { border-radius: 6px; } .bg-green { background: seagreen; }
.text-white { color: white; } .no-border { border: none; }
</style>
<button class="px-3 rounded bg-green text-white no-border">Купить</button>
<button class="px-3 rounded bg-green text-white no-border">В корзину</button>
<button class="px-3 rounded bg-green text-white no-border">Оформить</button>Чтобы поменять цвет всех кнопок, придётся исправить каждую. Повторяющийся набор выносят в компонент фреймворка или в обычный класс .button.