Введение в CCSS – компонентный CSS
CCSS организует CSS вокруг независимых компонентов интерфейса: карточек, кнопок, рейтингов. Подход объединяет правила именования, структуру файлов и ограничения зависимостей. Пример на Sass содержит полный код примесей, команды сборки и разметку рейтинга. Его можно перенести в отдельный проект без подключения сторонней библиотеки примесей.
Что такое компонентный CSS
Компонентный CSS связывает каждый блок интерфейса с собственными стилями. Например, файл рейтинга описывает заголовок, звезды и активное состояние звезды. Страница размещает рейтинг, но не управляет его внутренними элементами.
В этой статье CCSS обозначает набор архитектурных соглашений.
Браузер получает обычный CSS и ничего не знает об этих соглашениях. Имена классов помогают разработчикам соблюдать границы, но сами стили технически остаются глобальными.
Custom Elements и Shadow DOM решают другую часть задачи. Custom Elements позволяют определять собственные HTML-элементы, а Shadow DOM создает отдельное дерево с границей действия стилей. CCSS можно применять и без этих механизмов.
Другие инструменты дополняют компонентную архитектуру:
- CSS Modules локализуют имена классов при сборке. Соглашения CCSS при этом помогают организовать файлы и зависимости.
- @layer задает порядок каскадных слоев. Слои помогают разделить базовые стили, библиотеки и компоненты.
- @scope ограничивает область применения селекторов. Правило не заменяет договоренности о внутреннем устройстве компонентов.
- Нативная вложенность CSS сокращает запись связанных селекторов. В отличие от Sass, она не поддерживает склеивание имен через
&-title.
Как CCSS связан с OOCSS, SMACSS и BEM
CCSS использует идеи нескольких подходов к организации CSS. Различайте их задачи: именование классов, распределение правил по категориям и повторное использование оформления.
SMACSS расшифровывается как Scalable and Modular Architecture for CSS. Подход разделяет стили на категории: базовые правила, раскладку, модули, состояния и темы.
BEM описывает интерфейс через блоки, элементы и модификаторы. CCSS сохраняет это разделение, но использует собственную сокращенную запись имен.
OOCSS делает акцент на разделении структуры и оформления, а также независимости объекта от контейнера.
| Критерий | OOCSS | SMACSS | BEM | CCSS в этой статье |
|---|---|---|---|---|
| Формат имен | Единого обязательного формата нет; классы отражают структуру и оформление | Имена отражают категории и состояния; возможны префиксы | Блок, элемент, модификатор; конкретная запись зависит от конвенции | ComponentName, ComponentName-elementName, ComponentName--modifierName |
| Организация файлов | По повторно используемым объектам | По категориям правил | По блокам и связанным с ними сущностям | ext/, base/, components/; отдельный файл компонента |
| Когда подходит | Когда повторяются структура и визуальное оформление | Когда нужно распределить существующие стили по категориям | Когда команда договаривается о границах блоков и именах | Когда нужны компонентные границы и понятная структура общего CSS |
Не переносите все соглашения одновременно. Выберите одну запись имен и закрепите ее в документации проекта.
Инструменты
CCSS не требует определенного препроцессора или таск-раннера. Для воспроизводимого примера достаточно Dart Sass и npm scripts. Отдельный инструмент обработки префиксов подключайте только при потребности проекта.
Sass и модульное подключение
Sass добавляет к CSS переменные, примеси и модульное подключение файлов. В примере используется синтаксис SCSS и реализация Dart Sass.
Less тоже подходит для компонентных стилей, но приведенные примеси рассчитаны на Sass.
Директива @use подключает модуль и создает пространство имен для его функций и примесей. Директива @forward позволяет собрать публичный интерфейс нескольких модулей. Для небольшого примера дополнительный объединяющий файл не нужен.
Сборка и вендорные префиксы
npm scripts запускают компилятор одной командой из корня проекта. Флаг --watch включает наблюдение за изменениями исходников. Синтаксис команд описывает документация командной строки Dart Sass.
Если проекту нужны вендорные префиксы, используйте Autoprefixer в цепочке PostCSS после Sass. Autoprefixer обрабатывает готовый CSS с учетом выбранных целевых браузеров.
Сам Sass автоматически префиксы не добавляет.
Для учебного рейтинга дополнительная обработка не требуется. Подключать библиотеку примесей ради этого примера тоже не нужно.
Принципы CCSS
Граница компонента должна оставаться понятной при изменении страницы. Проверяйте архитектуру на переносе блока, добавлении состояния и замене соседнего компонента.
Компонентная основа
Создавайте небольшие блоки с одной задачей. Рейтинг показывает оценку, карточка описывает товар, кнопка запускает действие. Один компонент может включать другой через разметку.
Многократно используемый компонент CSS может размещаться в различных частях дерева DOM и не требует использования только определенных типов элементов.
Модульность и изолированность
Не привязывайте оформление звезд к классу окружающей карточки.
Общие значения передавайте через дизайн-токены или CSS-переменные. Например, несколько компонентов могут читать переменную цвета акцента. Это явная зависимость от общей настройки, которую команда может документировать.
Возможность компоновки
Собирайте интерфейс из компонентов, модификаторов и небольших утилит. Модификатор меняет вариант блока, утилита выполняет узкую общую задачу.
Не превращайте внутренний элемент рейтинга в универсальную утилиту только ради сокращения кода. Одинаковое свойство в 2 компонентах еще не доказывает общую ответственность.
Предсказуемость и документация
Одиночный класс проще переопределить и найти в проекте.
Избегайте чрезмерно сложных селекторов: цепочки предков привязывают оформление к расположению компонента. После переноса блока такие правила могут перестать работать.
Документируйте обязательную разметку, доступные модификаторы и ограничения компонента. Добавьте 2 демонстрации рейтинга: обычную и с активными звездами. Такие примеры объясняют контракт лучше списка свойств.
Структура каталогов и имена
Разделите стили на 3 категории: внешние зависимости, базовые правила и компоненты. Храните их в ext/, base/ и components/ соответственно. Вспомогательный каталог mixins/ содержит примеси Sass для генерации селекторов.
Дерево проекта
Создайте отдельный каталог проекта с такой структурой. Каталог styles/ предназначен для результата компиляции.
project/
├── index.html
├── package.json
├── scss/
│ ├── main.scss
│ ├── ext/
│ ├── base/
│ │ ├── _base.scss
│ │ ├── _base-classes.scss
│ │ ├── _images.scss
│ │ ├── _animate.scss
│ │ └── _bootstrap-overrides.scss
│ ├── mixins/
│ │ └── _bem.scss
│ └── components/
│ └── _ProductRating.scss
└── styles/
└── main.cssСхема показывает общий принцип разделения исходников и собранных стилей:

Редактируйте исходники в scss/.
Не правьте styles/main.css вручную: следующая сборка перезапишет изменения. Приведенное текстовое дерево задает пути для учебного примера.
Конвенция имен – упрощенный BEM
u-className– глобальные классы утилит.img-className– общие классы оформления изображений, если они нужны.animate-className– общие классы анимации.ComponentName– корневой класс компонента.ComponentName-elementName– элемент компонента.ComponentName--modifierName– модификатор компонента.ComponentName-elementName--modifierName– модификатор элемента.
Пишите имя компонента в UpperCamelCase: ProductRating. Для элемента используйте lowerCamelCase: ProductRating-starHolder. Один дефис отделяет элемент, 2 дефиса отделяют модификатор.
Модификатор добавляйте вместе с исходным классом. Например, активная звезда получает ProductRating-star ProductRating-star--active. Сам модификатор содержит только отличия активного состояния.
Архитектура
Структура каталогов помогает только при понятных правилах владения кодом. Отделите внешние зависимости от собственных изменений и назначьте каждому компоненту самостоятельную область ответственности.
Организация файлов
Каталог ext/ хранит внешние стили, если вы включаете их в репозиторий. Если зависимости устанавливает менеджер пакетов, не копируйте их туда без причины. Учебный пример оставляет этот каталог пустым.
Каталог base/ содержит стили, общие для приложения:
_base.scss– базовые правила для HTML-элементов, включая согласованный сброс или нормализацию стилей._base-classes.scss– небольшие утилиты с префиксомu-._images.scss– общие классы оформления изображений, если проект их использует._animate.scss– общие анимации и связанные классы._bootstrap-overrides.scss– глобальные переопределения стилей Bootstrap, только если проект его использует.
Не встраивайте все изображения в CSS как Data URI. Встроенное изображение увеличивает файл стилей и не кешируется отдельно от него. Используйте отдельные файлы по умолчанию; небольшую SVG-иконку можно встроить при обоснованной потребности.
Собирайте глобальные переопределения фреймворка в одном месте.
Сначала изучите специфичность исходного селектора. Не добавляйте цепочки родительских классов только ради победы в каскаде.
Компоненты без привязки к фреймворку
Храните стили рейтинга в components/_ProductRating.scss. Для небольшого приложения достаточно одного каталога компонентов. При росте проекта разделите компоненты по функциям или областям интерфейса.
Родительская карточка управляет размещением рейтинга, но не цветом его звезд. Если рейтинг нужен в компактном виде, добавьте ему собственный модификатор. Так изменение карточки не нарушит рейтинг на другой странице.
Порядок правил внутри файла удобно согласовать с порядком элементов разметки. Сначала опишите корень, затем заголовок, звезды и состояния.
Пример компонента
Соберите статический рейтинг с 5 звездами, из которых активны 3. Пример использует 2 примеси: e() создает класс элемента, m() создает класс модификатора.
Подготовка файлов и npm
Для команд нужны установленные Node.js и npm. Откройте терминал в корне отдельного проекта. Команды node --version и npm --version должны вывести номера установленных версий.
- Создайте каталоги и исходные файлы по текстовому дереву. Пока оставьте все файлы в
base/пустыми. - Выполните
npm init -y. В корне появитсяpackage.json. - Выполните
npm install --save-dev sass. npm добавит Sass в зависимости разработки и создаст файл блокировки зависимостей. - Добавьте в
package.jsonполеscriptsиз примера. Если поле уже есть, добавьте в него только 2 команды.
"scripts": {
"css:build": "sass --no-source-map scss/main.scss styles/main.css",
"css:watch": "sass --no-source-map --watch scss/main.scss:styles/main.css"
}Это фрагмент JSON, который нужно поместить внутрь основного объекта. Отделяйте соседние поля запятыми. В существующем проекте сначала сохраните изменения в системе контроля версий.
Полный код примесей
Запишите в scss/mixins/_bem.scss обе примеси:
@mixin e($name) {
@at-root #{&}-#{$name} {
@content;
}
}
@mixin m($name) {
@at-root #{&}--#{$name} {
@content;
}
}Символ & обозначает родительский селектор Sass. Директива @at-root выводит правило за пределы текущей вложенности. Поэтому примесь создаст .ProductRating-title без селектора предка .ProductRating.
Эти компактные примеси рассчитаны на один простой класс в родительском селекторе. Не вызывайте их внутри списков селекторов, псевдоклассов или цепочек предков.
Стили ProductRating и точка входа
Сохраните код компонента в scss/components/_ProductRating.scss:
@use "../mixins/bem";
.ProductRating {
display: inline-flex;
flex-direction: column;
gap: 0.25rem;
@include bem.e(title) {
margin: 0;
font-size: 1rem;
}
@include bem.e(star) {
color: #777;
@include bem.m(active) {
color: #9a6700;
}
}
}Создайте точку входа scss/main.scss. Подключения базовых файлов показывают порядок организации проекта; в примере эти файлы пустые.
@use "base/base";
@use "base/base-classes";
@use "base/images";
@use "base/animate";
@use "base/bootstrap-overrides";
@use "components/ProductRating";Sass позволяет опускать начальное подчеркивание и расширение подключаемого файла.
Каждый модуль самостоятельно подключает нужные ему примеси через @use. Подключение примесей только в main.scss не сделает их доступными внутри компонента.
Компиляция и готовый CSS
Выполните в корне проекта npm run css:build. Компилятор создаст styles/main.css с такими правилами:
.ProductRating {
display: inline-flex;
flex-direction: column;
gap: 0.25rem;
}
.ProductRating-title {
margin: 0;
font-size: 1rem;
}
.ProductRating-star {
color: #777;
}
.ProductRating-star--active {
color: #9a6700;
}В готовом файле не должно остаться @include или Sass-переменных. Комментарии в обычном CSS записывают через /* комментарий */; синтаксис // для него не подходит.
Разметка и проверка в браузере
Сохраните в корне проекта файл index.html:
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Пример ProductRating</title>
<link rel="stylesheet" href="styles/main.css">
</head>
<body>
<div class="ProductRating">
<p class="ProductRating-title">Оценка товара</p>
<div role="img" aria-label="Оценка: 3 из 5">
<span class="ProductRating-star ProductRating-star--active" aria-hidden="true">★</span>
<span class="ProductRating-star ProductRating-star--active" aria-hidden="true">★</span>
<span class="ProductRating-star ProductRating-star--active" aria-hidden="true">★</span>
<span class="ProductRating-star" aria-hidden="true">★</span>
<span class="ProductRating-star" aria-hidden="true">★</span>
</div>
</div>
</body>
</html>Откройте index.html в браузере. Вы увидите заголовок и 5 звезд: первые 3 окрашены иначе. Текстовая метка сообщает оценку пользователям скринридера.
Пример показывает оценку, но не реализует интерактивное голосование.
Для автоматической пересборки запустите npm run css:watch. Измените цвет активной звезды в SCSS и сохраните файл. После сообщения об успешной компиляции обновите страницу браузера.
Наблюдение пересобирает CSS, но само страницу не перезагружает.
Если стили отсутствуют, проверьте наличие styles/main.css и адрес в href. Если Sass сообщает об отсутствующем модуле, сравните путь из ошибки с деревом файлов. Названия и регистр букв должны совпадать.
Остановите наблюдение сочетанием Ctrl+C. Чтобы отменить эксперимент в существующем репозитории, восстановите измененные исходники и файлы зависимостей из сохраненной версии. Затем заново соберите CSS.
Ошибки при внедрении CCSS
Большинство архитектурных проблем возникает при нарушении границ компонентов. Проверяйте селекторы и места изменений до добавления новых общих правил.
- Глубокая вложенность селекторов. Правило
.Catalog .Card .ProductRating .ProductRating-starсвязывает рейтинг с конкретной страницей. Оставьте стили звезды на ее собственном классе. - Зависимости между внутренними элементами. Селектор
.Card .ProductRating-starпозволяет карточке менять чужой компонент. Добавьте рейтингу модификатор или документированную CSS-переменную. - Правки внутри ext/. Ручные изменения внешней библиотеки усложняют обновление. Храните собственные переопределения отдельно от исходников зависимости.
- Модификатор без базового класса. Класс
ProductRating-star--activeзадает только отличия. Сохраняйте рядомProductRating-star. - Слишком общие утилиты. Класс
u-starHolderскрывает принадлежность разметки рейтингу. Если правило обслуживает только рейтинг, используйтеProductRating-starHolder. - Ручная правка результата сборки. Исправление в
styles/main.cssпропадет при компиляции. Меняйте соответствующий SCSS-файл и повторяйте сборку.
Как внедрять CCSS в существующий проект
Если проект использует глобальный CSS, начните с одного самостоятельного блока. Перенесите его правила в отдельный файл и назначьте компонентные классы. Затем проверьте блок в 2 разных контейнерах: оформление должно сохраниться.
Если проект уже использует CSS Modules, сохраните локальные классы. Возьмите из CCSS разделение ответственности и правила зависимостей.
Массовое переименование ради другой конвенции добавит работу без обязательной пользы.
Если приложение зависит от CSS-фреймворка, сначала отделите его стили от собственных переопределений. Затем переводите компоненты постепенно, сохраняя рабочую сборку после каждого изменения.
Совет от нашей редакции: переносите компонент вместе с демонстрационной разметкой. По ней проще заметить скрытую зависимость от страницы до изменения остальных стилей.
Популярное за неделю
- Как создать сайт самому в 2026: 4 способа + пошаговая инструкция 34 мин чтения
- Лучшие конструкторы для создания сайтов — плюсы, минусы и сравнения 22 мин чтения
- overflow hidden что это и почему обрезка не работает 6 мин чтения
- 50 примеров CSS3‑кнопок с эффектами для сайта 5 мин чтения
- 17 эффектных CSS‑анимаций с готовыми примерами 3 мин чтения
- 19 CSS‑спиннеров и прелоадеров для загрузки 5 мин чтения
Комментарии
Знатоки подскажите!
Я с подобным подходом работаю давно, но до сих пор не нашёл в SCSS лаконичного способа пробрасывать влияние модификатора блока на его элементы.
Например, мне нужно при добавлении модификатора "--highlight" к ".ProductRating" изменить фон у элемента "-title" в итоговом css должно получиться что-то вроде:
.ProductRating--highlight .ProductRating-title {background: red;}
Как нужно модифицировать код из этой статьи чтобы получить желаемое поведение?
.ProductRating.ProductRating--highlight {
/**bem**/
.ProductRating {
&-title{..some actions}
}
}