Рассказываю о небольшом цветовом фреймворке, который используется в нашей ДС. Сначала, как обычно, небольшой обзор бест-практисов, а затем мой велосипед. Пойдем по порядку.

Сколько нужно цветов

У нас "Заказчиками" цветов являются продуктовый дизайнер, маркетинг и разработка.

Что нужно для счастья простому дизайнеру?

Что нужно маркетингу?

Что нужно разработке?

Окей, а сколько оттенков каждого из цветов нужно? Не самый простой вопрос, между прочим.

Способ 1

Чтобы сделать один раз и хватило, обычно делают так:

Изменяя яркость и/или насыщенность с каким-либо шагом (он может быть динамическим), генерируется набор из примерно десяти оттенков каждого цвета. Два-три варианта будут использоваться часто, а остальные будут не очень часто.

Чтобы как-то проще ориентироваться какие оттенки используются только в самых красивых макетах, а какие постоянно — можно сделать так:

Способ 2

Можно, конечно, попробовать пойти от обратного и добавлять цвета по мере необходимости. Но это грозит неконтролируемым ростом их количества и мутными обоснованиями добавления нового цвета.

— Ну ты же видишь, что ни один из 49 оттенков серого, которые у нас уже есть, сюда не подходит, с ними выглядит плохо, нужен еще один, да, для иконки со стрелочкой, смотри как хорошо сразу стало.

Ну или наоборот, что тоже не ок:

— У нас уже есть отличный брендовый красный, который мы используем для всего, почему бы не использовать его и для ошибок тоже, зачем нам еще один красный?

Совет для самураев, выбравших этот путь

При таком подходе лучше давать цветам имена не привязанные к какой-либо шкале. Но, в целом, мне не нравятся такие беcсистемные истории. Что-то поменять в палитре составленной таким способом с предсказуемым результатом очень сложно.

Способ 3

Еще можно прописывать для каждого цвета стейты. Default, hover, pressed, и т.д. Тогда цвет становится атрибутом конкретного элемента. Но для этого, как мне кажется, должно быть выполнено два условия — очень ограниченное число интерактивных элементов и высокая дизайн-зрелость продукта.

Именуется это как-то так
Color name / Default
Color name / Hover
Color name / Disabled

Описанное выше есть в том или ином виде в любом проекте. Дальше мой велосипед.

Фреймворк

В предыдущих заметках я описывал свой подход к библиотекостроению и упоминал референсную библиотеку. У нас несколько продуктов и нужен был инструмент, который позволял бы добавлять продуктам индивидуальности. При этом хотелось бы без проблем заимствовать компоненты из одного продукта в другой без перекрашивания или, хотя бы, делая это по какой-то понятной логике.

Я разделил набор цветов на 2 части:

Основная часть — одинаковая для всех продуктов. Чай.

  • Base — палитра серого;

  • BG — фон;

  • Functional — для всяких функциональных штук вроде ссылок и ошибок.

Дополнительная — уникальная надстройка для продукта. Сахар.

  • Brand — цвета бренда, используемые в продукте;

  • Promo — акцентные цвета для всяких промо-историй.

Можно пить чай без сахара, можно добавить его чуть-чуть, а можно высыпать целую сахарницу. В каждом нашем продукте есть общий чай и свой сахар. Можно назвать ром с колой, тоже норм.

Семантика

Цвета обычно помогают считывать положение элементов в иерархии экрана. Яркая кнопка — главный элемент на экране, серый текст — не главный, как-то так. Если сгруппировать все цвета в интерфейсе по их назначению и важности, то добавится семантическая составляющая и немного повысится консистентность.

Для серого оказалось достаточно четырех степеней важности.

Для фона двух.

Цвета для всяких функциональных штук одинаково важны, их разделил по назначению, а не по важности.

Бренд.

У промо-цветов тоже нет каких-либо приоритетов, только названия: желтый, зеленый и т. д.

Подобного набора цветов обычно недостаточно, было решено добавить немного вариативности за счет сдвигов и градиентов. У каждого цвета может быть несколько вариантов, подчиняющихся определенным правилам, а может и не быть, если они пока не нужны.

Сдвиги

Сдвиги — небольшие отклонения от основного цвета.

В принципе, со сдвигами мы получаем примерно ту же историю с ранжированием оттенков по частоте использования, но с более семантичным неймингом и некоторыми другими бонусами.

Градиенты

Для каждого цвета может быть градиент, построенный на его основе, а может и не быть. А может быть только градиент, из которого можно будет получить базовый цвет.

Удобно, когда градиент получается из основного цвета по какой-то логике, например, сдвигом яркости на 16 пунктов :)
Удобно, когда градиент получается из основного цвета по какой-то логике, например, сдвигом яркости на 16 пунктов :)

Инверсии

У нас нет темной темы, но часто появляется потребность разместить что-то на контрастном фоне. Например, бахнуть текст не на белом фоне экрана, а на темно-синем банере. Или, вдруг, на одном из экранов использовать не белые карточки на сером фоне, а черные на черном. Для этого используются "инвертированные" версии цветов.

Все компоненты, а с ними и макеты страниц, при необходимости инвертируются. Каждый цвет заменяется на его "инвертированную" версию и начинает движение в обратном направлении.

Конечно, не все цвета инвертируются "в лоб", некоторым инверсия не нужна. Например, цвет ошибки подобран таким образом чтобы корректно отображаться и на светлой и на темной подложке.

Нейминг

В фигме структура следующая:

Часть фреймворка / Тип / Группа_Модификатор группы / Имя
Tea / Solid / Base / Primary_Inverted / Default 
Sugar / Gradient / Brand / Secondary / Up

Есть мнение, что токены должны иметь одинаковый нейминг в фигме и в коде. Но не все так просто. Паттерны работы с цветом в фигме и верстке отличаются. Сделав все одинаковым, мы прогнем дизайнера и получим кривые группы цветов в фигме с которыми ему будет сложно работать. Поэтому для цветов стоит описать naming convention, которая опишет принципы по которым цвета именуются в фигме и как этот нейминг должен переноситься в код. В итоге всем должно быть ок.


Идея со сдвигами была подсмотрена в цветовой схеме Opium.Fill.