Цветовая система и брендовые палитры
1) Зачем формализовать цвет
Цвет — это не набор «хороших оттенков», а управляемая система для:- узнаваемости бренда и визуальной консистентности,
- читаемости и доступности (WCAG),
- масштабирования интерфейсов (темы, платформы, локали),
- предсказуемых A/B-экспериментов (контраст, CTR, ошибки).
2) Основания системы: модели и метрики
OKLCH (рекомендуется): перцептуально равномерная, удобно контролировать светлоту `L` и насыщенность `C` при сохранении оттенка `H`.
Lab/LCH: также годится; OKLCH стабильнее по восприятию.
sRGB: конечное пространство отображения; итоговые значения всегда валидируем в sRGB и по WCAG.
Контраст (WCAG 2.2): базовый текст ≥ 4.5:1, крупный ≥ 3:1; критические уведомления — целиться в AAA (7:1) там, где это возможно.
3) Слои системы: от бренда к семантике
1. Бренд-ядро: 1–2 фирменных оттенка (+ поддерживающий акцент).
2. Семантика интерфейса: роли (`primary`, `secondary`, `success`, `warning`, `danger`, `info`, `neutral`).
3. Шкалы тонов: шаги по светлоте (напр., 25/50/100…900).
4. Темы: `light` / `dark` (+ high-contrast, AMOLED).
5. Состояния: `default/hover/active/focus/disabled`.
6. Контекст: поверхностей (`bg/base`, `bg/subtle`, `bg/elevated`) и текста (`fg/primary`, `fg/secondary`, `fg/muted`).
7. Визуализация данных: отдельные дискретные и непрерывные палитры.
4) Бренд-ядро: выбор и ограничители
Выберите главный оттенок (Hue) и определите рабочую светлоту для бренда в светлой и темной темах (часто `L≈0.60–0.70` для заливки кнопок в light и `L≈0.70–0.80` для текста/иконок в dark).
Ограничьте хрому `C`: высокие `C` красиво на баннерах, но ломают читаемость в UI — держите 2 версии: «маркетинговая» (насыщенная) и «продуктовая» (сдержаннее).
Зафиксируйте вариативы: основной (`brand/primary`), альтернативный (`brand/alt`) и нейтральная опора (`neutral`).
5) Шкалы тонов (tonal scales)
Цель — получить равномерные ступени светлоты с управляемой насыщенностью:- Для OKLCH двигайте `L` ступенями (напр., 0.98→0.90→0.80→…→0.18), а `C` слегка уменьшайте к краям шкалы, чтобы избежать «грязи» в светлых и «мутности» в темных.
- Фиксируйте контрольные точки: `50/100/300/500 (key)/700/900`.
- На каждом шаге проверяйте контраст пары с базовым фоном и с ожидаемым цветом текста.
Пример шкалы brand/primary (OKLCH, приближенно)
brand.primary.50 = oklch(0.98 0.03 230)
brand.primary.100 = oklch(0.94 0.05 230)
brand.primary.300 = oklch(0.86 0.08 230)
brand.primary.500 = oklch(0.74 0.10 230) # ключевой тон brand.primary.700 = oklch(0.56 0.09 230)
brand.primary.900 = oklch(0.32 0.07 230)
6) Семантические роли и маппинг
Разделяйте бренд и семантику: «успех» не обязан быть бренд-зеленым.
role.primary.bg -> brand.primary.500 role.primary.text -> fg.on-primary # ≥ 4.5:1 к role.primary.bg role.success.bg -> green.500 role.warning.bg -> amber.500 role.danger.bg -> red.500 role.info.bg -> blue.500 role.neutral.bg -> gray.200/700 (light/dark)
Тексты `on-` рассчитываются автоматически (см. §10).
7) Светлая/темная темы и поверхности
Определите базовую шкалу поверхностей и текста:
light:
bg/base = oklch(0.98 0.01 260)
bg/subtle = oklch(0.96 0.01 260)
bg/elevated = oklch(0.93 0.01 260)
fg/primary = oklch(0.18 0.03 260) # ≈7:1 к bg/base fg/secondary = oklch(0.32 0.03 260) # ≥4.5:1 border = oklch(0.80 0.02 260)
dark:
bg/base = oklch(0.16 0.01 260)
bg/subtle = oklch(0.20 0.01 260)
bg/elevated = oklch(0.24 0.01 260)
fg/primary = oklch(0.90 0.02 260)
fg/secondary = oklch(0.78 0.02 260)
border = oklch(0.34 0.02 260)
Сохраняйте равные цели контраста в обеих темах; избегайте «слепящих» белых на чистом черном — поднимайте `L` фона до ~0.16.
8) Состояния и интерактивность
Для каждой роли задайте состояния с контролируемым `ΔL` и `ΔC`:
button/primary:
default.bg = brand.primary.500 hover.bg = brand.primary.500 with +ΔC(0.01) -ΔL(0.02)
active.bg = brand.primary.700 focus.ring = brand.primary.300 # контраст кольца ≥ 3:1 к окружению disabled.bg= neutral.200 (light) / neutral.700 (dark)
text.on = auto-contrast(default.bg) # ≥ 4.5:1
9) Ответственность и WCAG
Базовый текст и иконки в управляющих элементах — ≥ 4.5:1.
Ключевые системные уведомления (KYC/AML, 18+, платежные ошибки) — целимся в AAA (7:1).
Состояния и границы полей — не ниже 3:1.
Ссылки отличайте не только цветом (подчеркивание/focus-стиль).
10) Автоподбор контрастного текста (`on-`)
Логика: при выборе заливки компонента вычислять `on-color`:1. По OKLCH определить предлаг. текст `L_on` так, чтобы `(L_text vs L_bg) ≥ 4.5:1`.
2. Если хрома высока, снизить `C_text` до 0.01–0.03.
3. Для темной темы поднимать `L_on` еще на 0.02–0.04, чтобы компенсировать глейр.
Псевдо-токен:
fg.on(colorX) = auto(colorX, targetContrast=4.5)
11) Визуализация данных
Категориальные палитры: 8–12 цветов, устойчивых к дальтонизму (избегайте пар «красный–зеленый» без альтернативных признаков).
Непрерывные: от `bg/elevated` к акценту с контролем контраста подписей.
Добавляйте паттерны/маркеры для различимости без цвета.
12) Международный контекст (культурные ассоциации)
Учитывайте локальные коннотации (напр., красный — опасность/внимание; золото — выигрыш/приз).
Для iGaming: избегайте конфликтов «успех/опасность» с брендовыми акцентами в одном экране; иконография и подписи важнее «яркости».
13) Интеграция в дизайн-систему
13.1 Именование токенов
color.{theme}.{role surface brand}.{state step}
примеры color.light.brand.primary.500 color.dark.role.success.bg color.light.surface.bg.base color.light.fg.on-primary
13.2 Токены (JSON / Style Dictionary)
json
{
"color": {
"light": {
"surface": { "bg": { "base": "oklch(0.98 0.01 260)"} },
"brand": { "primary": { "500": "oklch(0.74 0.10 230)" } },
"role": { "primary": { "bg": "{color.light.brand.primary.500}" },
"danger": { "bg": "oklch(0.62 0.12 25)" } },
"fg": { "primary": "oklch(0.18 0.03 260)",
"on-primary": "auto({color.light.role.primary.bg},4.5)" }
}
}
}
13.3 CSS-переменные (слой тем)
css
:root[data-theme="light"] {
--bg-base: oklch(0.98 0.01 260);
--brand-primary-500: oklch(0.74 0.10 230);
--fg-primary: oklch(0.18 0.03 260);
--on-primary: color-contrast(var(--brand-primary-500)); / автоподбор /
}
[data-theme="dark"] {
--bg-base: oklch(0.16 0.01 260);
--brand-primary-500: oklch(0.74 0.10 230);
--fg-primary: oklch(0.90 0.02 260);
--on-primary: color-contrast(var(--brand-primary-500));
}
13.4 Figma/документация
Компоненты используют только токены, прямые HEX/SRGB запрещены линтерами.
В библиотеке — страница «Матрица контраста»: таблица `fg × bg` с фактическими коэффициентами.
14) Процессы контроля качества
В дизайне: проверка контраста на артбордах (оба режима), отдельные пресеты для дальтонизма.
В коде: юнит-хелперы вычисляют контраст и падают при нарушениях; визуальные снепшоты для критичных экранов.
В CI/CD: проверка всех пар токенов и состояний, отчет с компонентом, темой и фактическим значением.
15) Специфика iGaming
Промо и турниры: используйте оверлей и ограничение `C` на фонах, чтобы текст не «тонул».
Ответственные уведомления (лимиты, 18+, риски) — искренне AAA.
Метрики/таблицы: числа и знаки изменений (↑/↓) различайте формой и контрастом, а не только цветом.
16) Чек-лист внедрения
- Определены бренд-оттенки и их тональные шкалы (OKLCH).
- Заданы роли, состояния и поверхности для двух тем.
- Автогенерация `on-` с целевым контрастом.
- Матрица `fg × bg` и тесты WCAG в CI.
- Отдельные палитры для датавиз (с поддержкой дальтонизма).
- Линтер стилей запрещает «сырые» цвета.
- Страница «Исключения и причины» в гайдлайне.
17) Анти-паттерны
Смешивать бренд-акцент с «успех/ошибка» в одном UX-сигнале.
Полагаться только на насыщенность для иерархии.
Не синхронизировать light/dark (контраст «уехал» в одной из тем).
Жесткий HEX без токенов → неконтролируемый дрейф интерфейса.
Краткое резюме
Стройте палитру сверху вниз: бренд-ядро → семантические роли → шкалы тонов → темы → состояния. Работайте в OKLCH, закрепляйте токены, автоматизируйте `on-` и WCAG-проверки. Отдельно ведите палитры для датавиз. Это даст консистентность бренда, читаемость и масштабируемость продукта.