На одном внутреннем мероприятии Илья Полянский рассказал о градиентах и цветовых моделях, а я записал и отредактировал его рассказ.
В работе над редизайном приложения Почты России мы пробовали разные способы подчеркнуть в визуальной коммуникации нашу уникальность. В том числе думали о градиентах. Под градиентами мы понимаем любые объекты, в которых один цвет переходит в другой. К ним можно отнести и тени. Оказалось, с градиентами связано много вопросов (вроде использования их в тёмной теме), и часть из них мы рассмотрели в этой статье.
Представьте любую из ситуаций:
Пришёл продакт-оунер и попросил сделать дизайн помоднее и посочнее, добавить градиентов на кнопки и отдельные экраны;
Дизайнер известно где почерпнул вдохновения и решил привнести в продукт чего-то нового;
Пришло пожелание от дизайн-директора или художественного руководителя, и дизайнер задумался о градиентах.
Задача кажется простой: открыть Фигму, заменить сплошную заливку линейным градиентом и выбрать два цвета. Дизайнер чувствует себя уверенно, у него всё быстро получается, но он замечает: что-то не то.
Такие градиенты в дизайн-сообществе принято называть грязными. Это ощущение сложно объяснить словами. Если увеличить изображение, то где-то в середине перехода можно увидеть серое пятно. Даже подорожник не спасёт этот градиент.
В Фигме при построении перехода от цвета А к цвету Б почти всегда по умолчанию получается такой результат. Проблема не столько в программе, сколько в дизайнерах, которые не понимают цветовой модели RGB.
Если взять любой градиент, в котором начальный и конечный цвет комплементарны, посередине фигуры всегда будет цвет с нулевой насыщенностью (Saturation) и половинной яркостью (Brightness).
Компьютер работает с цветовой моделью RGB, в которой сложно понять, как строится цвет.
Если представить её в виде куба, в его ядре окажутся оттенки серого, поэтому все градиенты, проходящие через ядро (например, от жёлтого к синему) или где-то рядом, будут довольно грязными. Если градиент пройдёт не точно через центр куба, в середине перехода будет цвет с малой насыщенностью, который в контексте градиента тоже окажется грязным.
При переходе по поверхности куба (например, от жёлтого к зелёному) градиент будет чистым.
Если нужен чистый переход именно от жёлтого к синему, можно добавить промежуточную точку или несколько, чтобы получился радиальный переход (не обязательно в виде кривой, как на картинке, линии могут быть прямыми).
В цветовой модели HSB можно пропускать серые зоны, увеличивая значения Saturation и Brightness на 5−15 единиц. Hue не стоит увеличивать больше чем на 5 единиц, иначе появятся цвета, слабо связанные друг с другом.
Сделать это можно руками или с помощью сервисов, генерирующих радиальные переходы и подбирающих промежуточный цвет.
По умолчанию любой заданный фигуре градиент занимает одинаковым цветом примерно половину фигуры. На картинке 25% занято почти одинаковым красным (Hue 0−15) и ещё 25% — голубым (Hue 160−175). Чтобы это исправить, надо вынести ползунки градиента немного за пределы фигуры.
Возникает вопрос: что если вынос ползунков — это внутренний параметр Фигмы, и его сложно будет реализовать в вёрстке.
В CSS эти параметры указаны вот такими жёлтыми значениями. У начального цвета параметр позиции будет иметь значение −13%, то есть градиент начнётся за границей фигуры. Промежуточный цвет будет ровно посередине (50%), а конечный цвет окажется на 13% за пределами фигуры (113%).
Также можно задать направление градиента — это первый параметр в нашем примере, равный 270 градусам (270deg).
Таким образом проблема с градиентами решена, и город может спать спокойно.
Комментарии (14)
dom1n1k
14.09.2024 17:33+7Сама идея перехода от декартовых координат к цилиндрическим - правильная. Но выбор для этого модели HSB, вероятно, наихудший из возможных. Автор недоразобрался в теории и вынужден шаманить какие-то странные костыли типа сдвига тона или выноса точек за пределы фигуры. Всё это лишнее.
На самом деле нужно просто использовать OKLCh (олдскульную CIE LCh тоже можно, но практического смысла нет). И даже в CSS это будет работать из коробки (хотя фоллбек сделать желательно).
Ну и комментарий выше насчет гамма-коррекции правильный - это чуть менее полноценное, но тоже вполне рабочее решение.
lam0x86
14.09.2024 17:33+1Тоже не понял, зачем эти костыли с вычислением промежуточного цвета. Даже я, кодер-фронтендщик, знаю про oklch и oklab, а тут пост от дизайнера, который, по идее, должен в этом разбираться на порядок лучше. Может быть, Фигма не поддерживает другие пространства, кроме rgb? Если так, тогда статья имеет право на жизнь.
dom1n1k
14.09.2024 17:33+3Да, фигма умеет интерполировать цвет только в RGB, поэтому как раз промежуточная точка - нужный костыль. Я бы вычислил её в OKLCh и добавил бы, просто чтобы макеты нормально выглядели. Но рядом оставил бы комментарий, что в коде достаточно оставить только крайние, но указать
in oklch
. А вот все прочие телодвижения в статье лишние.yppro
14.09.2024 17:33Именно. Фигма не умеет делать градиенты. В Фотошопе как ни двигай Hue туда-сюда, Saturation всегда одинаковый, и градиенты всегда чистые. Быстро и просто, без костылей
dom1n1k
14.09.2024 17:33ФШ умеет учитывать гамма-коррекцию, поэтому там результаты значительно лучше.
Но вообще говоря, грязь в середине градиента можно получить и там тоже, хотя и менее выраженную (с оговоркой, что я пользуюсь относительно старой версией, возможно в последних уже иначе).ArkadiyMak
14.09.2024 17:33ФШ учитывает гамма-коррекцию только в режиме 32 бита на канал, по крайней мере в версии CS6. На 8 и 16 битах градиенты грязные, размытие по Гауссу затемняет изображение, ну и так далее.
dom1n1k
14.09.2024 17:33Вообще у ФШ есть настройка, учитывать ли гамму. Но там написано blending gamma, то есть видимо это для смешивания слоев. А мне что-то казалось, что она более широкого назначения.
SadOcean
14.09.2024 17:33+1Проблема может быть не просто в том, что цвет градиента средний, а в том, что сами цвета имеют не линейную, а квадратичную зависимость.
То есть на самом деле разница между 000000 и 888888 гораздо меньше, чем между 888888 и FFFFFF.
Таким образом, когда мы линейто интерполируем между 0000FF и 00FF00, в середине у нас есть некий 008888, который в 2 раза более тусклый, нежели настоящий цвет между этими значениями. Потому то градиент в середине и выглядит серым.
Существуют скорректированные формулы градиентов (квадратичная интерполяция) и более продвинутые цветовые пространства, не имеющие этой проблемы, ими и нужно пользоваться.
Хотя авторский хак и решает эту проблему похожим способом.vadimk91
14.09.2024 17:33линейто интерполируем между 0000FF и 00FF00, в середине у нас есть некий 008888
А почему же 008888, а не 008080 или не 007F7F? маски сетей вы явно не считали :)
Так-то да, глаз человека тоже совсем не линейный сенсорSadOcean
14.09.2024 17:33Лень было)
Вы правы, что-то такое будет.
Я ж программист, математика - это не мое.
yppro
14.09.2024 17:33Сделать это можно руками или с помощью сервисов, генерирующих радиальные переходы и подбирающих промежуточный цвет.
ОК, пробуем данный сервис:
1) Тыкаем пипетку в образец автора (который Бро), получаем:
#FD0302 и #04FDEC
2) Закидываем в чудо-сервис
3) Измеряем серединку: #6a6e74. То есть, красивый серый цвет.
iShrimp
Самый очевидный фикс для таких градиентов - учесть гамма-коррекцию.
Средний между жёлтым #FFFF00 и синим #0000FF цвет - это не #7F7F7F и не #808080. Средний цвет приблизительно равен #BABABA. Вот так примерно выглядит математически корректный линейный градиент:
ArkadiyMak
А вот градиенты из начала статьи с учетом гамма-коррекции. И грязи как не бывало.