Цветовые примитивы и палитры
Цветовые примитивы — это конкретные цвета палитр Framework, единственный источник цветовых значений. Через них меняется фирменный цвет: роли и компоненты получают новые значения сами.
Палитры и тоны
Палитра — набор тонов одного цвета от самого светлого до самого тёмного. Во Framework восемь палитр:
| Группа | Палитры |
|---|---|
| Нейтральная | neutral |
| Акцентные | primary, secondary, tertiary |
| Статусные | info, success, warning, error |
Отдельно стоят три базовых цвета без тонов: --sf-white, --sf-black и
--sf-transparent.
У каждой палитры шестнадцать тонов: 98, 95, 90, 85, 80, 70, 60, 50, 40, 35, 30, 25, 20, 15, 10, 5. Тон — это светлота: 98 почти белый, 5 почти чёрный. Тона 100 и 0 заменяют белый и чёрный.

Шаг неравномерный: у краёв (светлые фоны, тёмный текст) нужны мелкие различия, поэтому там шаг 5; в середине, где цвет используется реже, — шаг 10.
Палитры построены по модели HCT (оттенок, насыщенность, тон), той же, что у
Material Design 3: тон в имени означает одинаковую воспринимаемую светлоту во
всех палитрах. Поэтому --sf-primary-40 и --sf-error-40 одинаково светлы, и
пара «тон 40 на белом» даёт сопоставимый контраст в любой палитре.
Палитра info по умолчанию совпадает с primary по значениям, но это
отдельная палитра: проект может развести «информацию» и «главный акцент», не
трогая одно ради другого.
Значения примитивов выбранного выпуска читаются в поставке, в
distr/core/css/core.css. Справочник «Все переменные»
примитивы не повторяет: в нём роли и остальные токены.
Правило имени примитива
--sf-{палитра}-{тон} сплошной цвет
--sf-{палитра}-{тон}--alfa-{ступень} тот же цвет с непрозрачностью {ступень} %
--sf-{white|black}--alfa-{ступень} полупрозрачные белый и чёрный
Примеры: --sf-primary-40, --sf-neutral-95, --sf-primary-50--alfa-12,
--sf-black--alfa-8.
Ступень прозрачности — целое число процентов из одной общей шкалы (см. Прозрачность), а
не доля от 0 до 1. Полупрозрачные примитивы записаны готовыми значениями,
поэтому браузеру не нужно их вычислять. Непрозрачность — целый байт,
ближайший к ступени: 12 % — это 31 из 255. В исходниках Framework такой
примитив записан восьмизначным шестнадцатеричным значением (#0073ed1f — тон
50 палитры primary при 12 %), в поставке core.css — тем же цветом в rgba():
rgba(0,115,237,0.12157).
Полупрозрачные ступени есть не у каждого тона, а только у тех, которыми что-то
рисуют. В основном это тон 50 (заливки и слои состояния в светлой теме) и
тон 90 (слои состояния в тёмной). Примитив, который ничто во
Framework не использует, не проходит контракт alpha-scale.
Примитивы не зависят от темы
Примитив — просто цвет. --sf-primary-40 одинаков в светлой и тёмной теме.
Тему учитывают только роли (Цветовые роли): именно роль задаёт, что в светлой теме
главный акцент — тон 40, а в тёмной — тон 80.
Поэтому примитив в стилях интерфейса — почти всегда ошибка: элемент,
окрашенный --sf-primary-40, в тёмной теме останется тёмно-синим на почти
чёрном фоне.
Замена палитры
Проще всего сменить фирменный цвет генератором темы:
он строит из одного цвета все восемь палитр и отдаёт их одним правилом CSS
(detail.css его событий или toCSS()), которое проект кладёт в свой CSS.
Как строятся палитры — в Как строятся палитры из одного цвета.
Палитру можно задать и вручную: переопределите тона палитры в слое проекта
(см. Как переопределять правильно). Роли ссылаются на примитивы через var(), поэтому обе темы
получат новые значения сами:
@layer project {
:root {
--sf-primary-40: #123456;
--sf-primary-80: #9ab0c8;
}
}
Пример сокращён: он показывает два тона из всех, которые нужно заменить.
Роли палитры primary читают такие примитивы (все — в core.css; компоненты
примитивы напрямую не читают, поэтому замена доходит до каждого компонента):
| Что | Примитивы |
|---|---|
| Тона | --sf-primary-10, -20, -30, -35, -40, -50, -60, -80, -85, -90 |
| Полупрозрачные ступени тона 50 | --sf-primary-50--alfa-4, -8, -12, -16, -20, -24, -28, -32 |
| Полупрозрачные ступени тона 90 | --sf-primary-90--alfa-4, -8, -12, -24 |
Роли палитры info читают меньше ступеней:
| Что | Примитивы |
|---|---|
| Тона | --sf-info-10, -20, -30, -35, -40, -50, -60, -80, -85, -90 |
| Полупрозрачные ступени тона 50 | --sf-info-50--alfa-12, -16, -20, -24, -28, -32 |
Ступеней --sf-info-50--alfa-4, -8 и полупрозрачных ступеней тона 90 у
info нет.
Остальные тона палитры (-5, -15, -25, -70, -95, -98) объявлены, но
ролями не читаются; заменять их можно для полноты.
Как строятся палитры из одного цвета
Палитры Framework построены в модели цвета HCT (Google material-color-utilities):
у палитры есть тон (hue) и насыщенность (chroma), а шестнадцать её тонов —
светлота от 98 до 5. Генератор темы и функции SF.ThemePalette берут тон и
насыщенность основного цвета и строят палитры по правилам:
| Палитра | Тон | Насыщенность |
|---|---|---|
primary |
тон цвета | насыщенность цвета |
secondary |
тон цвета | 20 |
tertiary |
тон цвета + 60 | 40 |
neutral |
тон цвета | 5 |
error |
25 | 85 |
warning |
60 | 60 |
success |
145 | 65 |
info |
тон цвета | насыщенность цвета |
Цвет Framework #005bbe читается как тон 265 и насыщенность 85, и по этим
правилам получаются ровно 128 примитивов поставки. Насыщенность читается так:
если цвет насыщен настолько, насколько его тон позволяет при его светлоте, —
так бывает у тёмного или светлого фирменного цвета, — насыщенность палитры
берётся не ниже 85, иначе — собственная насыщенность цвета. Тон и насыщенность можно задать и
числами — поля «Тонкая настройка» генератора или themeFromHct({hue, chroma}).
Вместе с тонами генератор пишет полупрозрачные ступени, которые ядро
выводит из тонов (--sf-<палитра>-<тон>--alfa-<ступень>, 98 переменных; список
— SF.ThemePalette.THEME_ALPHA): тема — 226 переменных, и заливки
*-container, фоны наведения и выбора следуют за новым цветом. Цвет Framework
даёт обратно и каждую полупрозрачную ступень поставки.
Как построить палитру
Палитру можно построить и в другом инструменте, который работает с моделью
HCT, например классом TonalPalette из пакета
@material/material-color-utilities
(TonalPalette.fromHueAndChroma(hue, chroma).tone(40) даёт тон 40), по
такому порядку:
- Возьмите оттенок (hue) и насыщенность (chroma) фирменного цвета.
- Получите при них шестнадцать тонов: 98, 95, 90, 85, 80, 70, 60, 50, 40, 35, 30, 25, 20, 15, 10, 5. Тон в HCT — та же светлота, что в имени примитива.
- Для каждой полупрозрачной ступени, которую читают роли, допишите к
шестнадцатеричному значению тона байт непрозрачности:
round(ступень × 255 / 100)в шестнадцатеричной записи. Например, тон 50#0073edпри 12 % —#0073ed1f(31 =1f), при 4 % —#0073ed0a. - Проверьте контраст пар, которые составят роли (ниже).
Контраст новой палитры
Роли берут из палитры одни и те же тона, поэтому новый тон обязан держать те
же пары, что и тон палитры по умолчанию. Для акцентной палитры (на примере primary):
| Пара | Тема | Порог |
|---|---|---|
Белый (--sf-on-primary) на тоне 40 (--sf-primary) |
Светлая | 4,5 : 1 |
Тон 40 (акцентный текст) на белом (--sf-surface-0) |
Светлая | 4,5 : 1 |
Тон 20 (--sf-on-primary) на тоне 80 (--sf-primary) |
Тёмная | 4,5 : 1 |
Тон 80 (акцентный текст) на --sf-neutral-5 (--sf-surface-0) |
Тёмная | 4,5 : 1 |
| Тон 50 (кольцо фокуса, цветная граница) на белом | Светлая | 3 : 1 |
Значения из этих пар в поставке по умолчанию:
| Примитив | Значение |
|---|---|
--sf-white (поверхность светлой темы) |
#ffffff |
--sf-neutral-5 (поверхность тёмной темы) |
#0f1115 |
--sf-primary-20 |
#002f67 |
--sf-primary-40 |
#005bbe |
--sf-primary-50 |
#0073ed |
--sf-primary-80 |
#acc7ff |
У палитры по умолчанию белый на тоне 40 даёт около 6,5 : 1, тон 20 на тоне
80 — около 7,7 : 1, тон 80 на --sf-neutral-5 — около 11 : 1. Если пара не проходит, сдвигают тон в палитре (тон 40
темнее, тон 80 светлее), а не роль. Пороги — в Контраст.
Контракты контраста (control-boundary, elevation-text и другие) — тесты
исходников Framework, в поставку они не входят. Палитру проекта проверяют
любым измерителем контраста по WCAG на тех же парах.
Правила замены
- переопределяйте все тона, на которые опираются роли этой палитры, и их полупрозрачные ступени — иначе часть ролей останется в исходном цвете;
- рекомендуется строить палитру целиком по модели HCT, а не подбирать тона по одному;
- палитры независимы.
info— своя палитра с собственными примитивами (--sf-info-*), а не производная отprimary: сменаprimaryеё не меняет. То же верно дляsecondaryиtertiary. Если информационный цвет должен следовать фирменному, переопределите и палитруinfo.
Смотрите также
- Цветовые роли — роли, которые ссылаются на примитивы;
- Прозрачность — шкала прозрачности;
- Контраст — пороги контраста;
- Своя тема проекта — роли и примитивы в CSS проекта.