Введение
ECSS (Extended CSS) — это надмножество CSS, которое компилируется на этапе сборки. Оно позволяет описывать состояния и варианты компонента прямо в файле стилей, не дублируя логику в JavaScript, и при этом даёт полную типизацию в TypeScript и минимальный рантайм.
Что такое ECSS?
Любой валидный CSS является валидным ECSS. Поверх привычного синтаксиса ECSS добавляет несколько директив, которые превращают .ecss-файл в типизированный компонент:
@block— именованный компонент стилей;@param— параметр, управляющий тем, какие правила применяются;@if/@elseif/@else— условные стили на основе параметров;@enum,@const,@element,@import,@external— перечисления, константы, вложенные элементы и работа с несколькими файлами.
Компилятор превращает .ecss-файл в обычный статический CSS плюс типизированный модуль, который импортируется в код приложения.
Какую проблему решает ECSS
Обычно логика состояний компонента размазана между двумя местами: классы объявлены в CSS, а решение «какой класс применить» живёт в JavaScript. Каждый новый вариант требует правок и там, и там, а связь между значением пропа и классом ничем не гарантирована.
ECSS переносит эту логику в стили. Компонент не знает ни о каких классах — он лишь передаёт параметры.
Как это выглядит
/* Button.ecss */
@enum Variant {
values: "primary", "danger", "ghost";
}
@block Button {
@param --variant Variant;
@param --disabled? boolean;
display: inline-flex;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
@if (--variant == "primary") {
background: #646cff;
color: #fff;
}
@if (--disabled) {
opacity: 0.4;
cursor: not-allowed;
}
}Импортируем сгенерированный компонент и передаём параметры — сборка className и подстановка нужных стилей происходят автоматически:
import { EButton } from './Button.ecss';
<EButton as="button" params={{ variant: 'primary' }}>
Кнопка
</EButton>;TypeScript знает допустимые значения variant из объявления @enum — передать несуществующий вариант не получится.
Ключевые особенности
- Надмножество CSS. Знакомый синтаксис; добавляете только то, что нужно.
- Состояния без JS. Параметры (
@param) и условные стили (@if) описываются в.ecss-файле, а не в компоненте. - Полная типизация. Для каждого импорта
*.ecssгенерируются точные типы — автодополнение и проверка типов работают из коробки. - Любой фреймворк. Адаптеры генерируют компоненты для React, Vue, Svelte и SolidJS; есть и адаптер для чистого DOM.
- Сборка, а не рантайм. В браузер попадает статический CSS — нет runtime-оверхеда, работает с SSR без дополнительной настройки.
- Минимальный рантайм. В бандл добавляется лишь крошечный хелпер для сборки классов и CSS-переменных.
- Поддержка в редакторе. Расширение для VS Code даёт подсветку синтаксиса, диагностику ошибок и hover-подсказки.
Как это работает
- Вы пишете
.ecss-файлы с блоками, параметрами и условиями. - Компилятор (
@ecss/compiler) превращает их в статический CSS и типизированный JS-модуль, а адаптер — в компоненты для вашего фреймворка. - Плагин сборщика (
@ecss/vite-plugin) подключает всё это в проект, а конфигурация (@ecss/config) общая и не привязана к конкретному сборщику.
Что дальше?
- Сравнение — чем ECSS отличается от CSS Modules и styled-components
- Модульная система — разбивка стилей на несколько файлов
@block— основная директива и полный синтаксис- Адаптеры: React — генерация компонентов
- Конфигурация — настройка адаптеров и сборки