Палитра для веб-разработки

Page Content

Палитра для веб-разработки

Дизайнерам и фрондендерам посвящается. Сказ о том⁠, как с палитрой удобно работать.

Речь не о том как выбрать палитру цветов, а о том⁠, как именно с ней работать⁠: к какому виду её привести⁠, как сделать так⁠, чтобы по ходу разработки не пришлось цвета делать «чуть-чуть поярче».

Публикация от ⁠.

Из жизни

Для примера возьмём палитру цветов сайта lonelyplanet.com⁠. Эта палитра  — часть большого Style Guide от команды проекта.

Ниже представлены основные цвета данной палитры.

#142B44
DARKBLUE
#1D508D
NAVBLUE
#297CBB
LPBLUE
#288AD6
LINKBLUE
#0FDEBD
TEAL
#16C98D
GREEN
#FEEF6D
YELLA
#FFC83F
ORANGE
#FA5E5B
RED
#BF538D
PLUM

Палитра имеет вспомогательные цвета⁠.

#2C3643
DARKGRAY
#3B444F
TITLEGRAY
#67747C
BODYGRAY
#99A9B3
LIGHTGRAY
#DBE6EC
SUBDUEGRAY
#684E79
MAUVE
#FF708E
PINK
#47A899
DARKCYAN
#8ABEE5
SOFTBLUE
#C7E6AA
SOFTGREEN
#CFCBAF
BEIGE
#582C2B
MAROON
#841E1B
DARKRED
#2C3643
COLOR-PALETTE

Палитра разработана дизайнером, а разработчик перенес палитру «⁠как есть⁠» в Sass для дальнейшей работы⁠. Далее мой коллега заводит пул переменных со значениями цветов⁠. Мы ведь же уже все⁠, пользуемся препроцессорами, да?

$darkblue : #142b44 !default
$navblue  : #1d508d !default
$lpblue   : #297CBB !default
$linkblue : #288ad6 !default
$teal     : #0FDEBD !default
$green    : #16c98d !default
$yella    : #feef6d !default
$orange   : #ffc83f !default
$red      : #fa5e5b !default
$plum     : #bf538d !default

Полный исходный код таблицы переменных доступен на github.com⁠. Что не так с этой палитрой?

  1. Отсутствует визуальная структура / Да, признаться, я чуть изменил структуру, объединив четыре группы цветов в две⁠, но даже в исходном варианте, ориентироваться в палитре не легче⁠, палитра представляет собой линейный неупорядоченный набор⁠;
  2. Названия цветов не отражают сути / Вот зачем⁠, мне как разработчику⁠, знать что цвет #684E79 — это не просто пурпурный, а именно Mauve⁠? Или как мне «⁠на лету⁠» понять что lpblue темнее или светлее navblue⁠?
  3. Разное количество оттенков каждого цвета (тона) / Различное количество оттенков одного цвета со временем неизбежно приведет к тому⁠, что отсутствующие оттенки других цветов будут созданы и общее количество цветов используемых на сайте будет расти⁠, расти неупорядоченно. Так почему бы не сделать это сразу⁠, системно?

Далее мой коллега создаёт функциональный слой переменных. Это перечень переменных, каждая из которых⁠, несёт в себе цвет для конкретной сущности в конкретном контексте/состоянии⁠. Т.е. цвета не создаются⁠, а назначаются⁠. Ниже представлена часть цветов функциональной палитры сайта lonelyplanet.com.

#FFC83F
SECTION-ACTIVITY
#C7E6AA
SECTION-ARTICLE
#297CBB
SECTION-ENTERTAINMENT
#684E79
SECTION-EVENT
#BF538D
SECTION-HOTEL
#3B444F
SECTION-NEED-TO-KNOW
#47A899
SECTION-RESTAURANT
#FF708E
SECTION-SHOPPING
#FA5E5B
SECTION-SIGHT
#16C98D
SECTION-TOUR
#3B444F
SECTION-TRANSPORT
#0FDEBD
SECTION-DESTINATION

Цвета исходной палитры (палитры дизайнера) в функциональной палитре могут использоваться несколько раз. Теоритически⁠, сущностей в интерфейсе намного больше чем самих цветов⁠.

Код функциональной палитры доступен на github.com. Ниже одна из его секций⁠.

$section--activity      : $orange !default
$section--article       : $softgreen !default
$section--entertainment : $lpblue !default
$section--event         : $mauve !default
$section--hotel         : $plum !default
$section--need-to-know  : $titlegray !default
$section--restaurant    : $darkcyan !default
$section--shopping      : $pink !default
$section--sight         : $red !default
$section--tour          : $green !default
$section--transport     : $titlegray !default
$section--destination   : $teal !default

Если посмотреть внимательнее на функциональную палитру и её код⁠, то можно обнаружить переменные, которые не наследуют ранее созданные цвета⁠, а создают свои⁠, например,

$body-background          : #f5f5f5 !default
$body-background-offset   : mix($lpblue, #fff, 5%) !default
$card-figure-bg           : #f4fbfe !default
$details-panel-bg         : mix($subduedgray, #fff, 15%) !default
$details-panel-border     : $subduedgray !default
$high-contrast-bg         : $titlegray !default
$high-contrast-fg         : $lightgray !default
$input-border             : $subduedgray !default
$new-header-grey-shadow   : rgba(3, 46, 92, 0.12)
$responsive-nav-bg        : mix($linkblue, #fff, 3%)
$responsive-nav-subnav-bg : mix($linkblue, #fff, 6%)

$highlight-error          : lighten($red, 25%) !default
$highlight-success        : lighten($green, 45%) !default
$highlight-warning        : lighten($yella, 20%) !default
$highlight-announcement   : mix($linkblue, #fff, 25%) !default

Такая организация кода — это следствие того⁠, что, во-первых⁠, некоторые цвета палитры дизайнера представлены сильно ограниченным количеством оттенков (3-4)⁠, а во вторых⁠, палитра не имеет системы/структуры⁠.

Двумерная палитра

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

Представление понятия «тон», в народе — «цвет» (изображение с сайта wikipedia.org)
Представление понятия «тон»⁠, в народе — «цвет» (изображение с сайта wikipedia.org⁠)

Тон (англ. hue) — одна из трёх основных характеристик цвета наряду с насыщенностью и светлотой⁠. В строгом колориметрическом смысле тон - ⁠это направление вектора цветности (вектора на диаграмме цветности с началом в точке белого и концом в данной цветности).

Направление может быть задано углом (⁠это и есть цветовой тон⁠), в то время как удаленность от точки белого задается в процентах и называется насыщенностью (степенью смешивания наиболее насыщенных цветов - спектральных или крайних пурпурных с белым⁠). Именно тон определяет название цвета⁠, например «красный», «синий», «зелёный».

Википедия

Назовите цвета односложно, понятно любому разработчику и дизайнеру⁠, например: $gray⁠, $blue⁠, $purple и $pink⁠.

Просто договоритесь, что синий в контексте данного конкретного проекта это не #0000ff⁠, а, скажем, #297CBB⁠. А все оттенки синего пусть наследуются от него⁠. Такое значение имеет цвет $lpblue из палитры lonelyplanet.com.

Примерно таким образом созданы и названы цвета в моём блоге⁠.

$gray:   hsl(  0,  0%, 50%);
$blue:   hsl(200, 80%, 50%);
$pink:   hsl(340, 80%, 50%);
$purple: mix($blue, $pink);

Настоятельно рекомендую «откалибровать» палитру. Я использую цветовую модель HSL для выравнивания цветов по насыщенности и светлоте⁠.

Кстати, вы можете использовать эту цветовую модель непосредственно на клиенте⁠, так как её поддержка в броузерах хороша⁠.

За базовый цвет каждого семейства оттенков цвета⁠, берём цвет у которого светлота равна 50%⁠. Тем самым⁠, как бы центрируем все цвета между черным и белым⁠. При этом⁠, «брендовые» цвета могут и не быть базовыми, главное, чтобы срез по светлоте проходил ровно по светлоте корпоративного цвета⁠.

Вот так выглядит палитра моего блога⁠.

5l
4l
3l
2l
1l
gray
1d
2d
3d
4d
5d
5l
4l
3l
2l
1l
pink
1d
2d
3d
4d
5d
5l
4l
3l
2l
1l
blue
1d
2d
3d
4d
5d
5l
4l
3l
2l
1l
green
1d
2d
3d
4d
5d
5l
4l
3l
2l
1l
red
1d
2d
3d
4d
5d
5l
4l
3l
2l
1l
mocca
1d
2d
3d
4d
5d

В моей палитре все цвета разложены с шагом в 10% по светлоте⁠. Шкала уровней отклонения светлости от базового цвета равна⁠: ±47, ±40, ±30, ±20, ±10. Крайние цвета имеют отклонение в 47% вместо 50%⁠, иначе бы они превратились в белые и черные цвета⁠.

Шаг между уровнями должен быть достаточным для визуального отличия, но не большим и не маленьким⁠, таким, чтобы не пришлось создавать промежуточные цвета и их не было слишком много⁠. Обычно, в моих проектах шаг составляет 10% светлости⁠.

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

Производные от базового цвета обозначены «говорящими» суффиксами-модификаторами⁠: $purple_3d⁠, $purple_2l и т.п.

$pink   : hsl(340, 80%, 50%);

$pink_5l: hsl(340, 80%, 95%);
$pink_4l: hsl(340, 80%, 90%);
$pink_3l: hsl(340, 80%, 80%);
$pink_2l: hsl(340, 80%, 70%);
$pink_1l: hsl(340, 80%, 60%);

$pink_1d: hsl(340, 80%, 40%);
$pink_2d: hsl(340, 80%, 30%);
$pink_3d: hsl(340, 80%, 20%);
$pink_4d: hsl(340, 80%, 10%);
$pink_5d: hsl(340, 80%, 5%);

Что эквивалентно записи с использованием Sass-методов lighten и darken⁠.

$pink   : hsl(340, 80%, 50%);

$pink_5l: lighten($pink, 45%);
$pink_4l: lighten($pink, 40%);
$pink_3l: lighten($pink, 30%);
$pink_2l: lighten($pink, 20%);
$pink_1l: lighten($pink, 10%);

$pink_1d:  darken($pink, 10%);
$pink_2d:  darken($pink, 20%);
$pink_3d:  darken($pink, 30%);
$pink_4d:  darken($pink, 40%);
$pink_5d:  darken($pink, 45%);

Наличие таких переменных позволяет более удобно работать с цветами палитры. Например, переменная $blue_1d может сделать текст синим⁠, со светлостью ниже на 10% от базового тона⁠. А $blue_1l — может повысить его светлость на 20% от предыдущего состояния, например, по hover⁠.

Уровни отклонения от базового цвета (⁠срезы по светлоте⁠), это не обязательно +10 или -20 по светлоте⁠, нужно воспринимать это как абстрактные «уровни».

Т.е. в обычной жизни нам даже не нужно знать⁠, что, например, $gray_4l соответствуют отклонению +33 по светлоте⁠, мы просто используем переменную по уровню⁠.

А если палитра уже существует⁠?

Метод разложения цветов по светлости и представления множества цветов палитры в виде двумерной палитры может быть полезен даже в том случае⁠, когда палитра и сайт уже существуют⁠. Для примера⁠, приведём в порядок палитру от lonelyplanet.com.

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

$red     : #fa5e5b  =  hsl(   1,  94%,  67% )
$orange  : #ffc83f  =  hsl(  43, 100%,  62% )
$yella   : #feef6d  =  hsl(  54,  99%,  71% )
$green   : #16c98d  =  hsl( 160,  80%,  44% )
$teal    : #0fdebd  =  hsl( 170,  87%,  46% )
$lpblue  : #297cbb  =  hsl( 206,  64%,  45% )
$linkblue: #288ad6  =  hsl( 206,  69%,  50% )
$darkblue: #142b44  =  hsl( 211,  55%,  17% )
$navblue : #1d508d  =  hsl( 213,  66%,  33% )
$plum    : #bf538d  =  hsl( 328,  46%,  54% )

Посмотрим внимательно на полученное hsl-представление цветов⁠. Цвета $lpblue и $linkblue равны по параметру «Hue» (цвет)⁠. А их параметры «насыщенность» очень близки⁠.

$lpblue  : #297cbb  =  hsl( 206,  64%,  45% )
$linkblue: #288ad6  =  hsl( 206,  69%,  50% )

Если чуть «похулиганить», то к данной группе можно добавить и другие цвета из основной палитры.

$lpblue  : #297cbb  =  hsl( 206,  64%,  45% )
$linkblue: #288ad6  =  hsl( 206,  69%,  50% )
$darkblue: #142b44  =  hsl( 211,  55%,  17% )
$navblue : #1d508d  =  hsl( 213,  66%,  33% )

С небольшим допущением, данные цвета можно заменить одним базовым и его производными по светлости⁠:

$lpblue  : #297cbb  =  hsl( 206,  64%,  45% )  ——>  hsl( 206,  69%,  45% )
$linkblue: #288ad6  =  hsl( 206,  69%,  50% )  ——>  hsl( 206,  69%,  50% )
$darkblue: #142b44  =  hsl( 211,  55%,  17% )  ——>  hsl( 206,  69%,  17% )
$navblue : #1d508d  =  hsl( 213,  66%,  33% )  ——>  hsl( 206,  69%,  33% )

Определим возможные уровни и создадим переменные.

$red     : #fa5e5b  =  hsl(   1,  94%,  67% )  ——>  hsl(   1,  94%,  67% )  =  $red_3l
$orange  : #ffc83f  =  hsl(  43, 100%,  62% )  ——>  hsl(  43, 100%,  62% )  =  $orange_2l
$yella   : #feef6d  =  hsl(  54,  99%,  71% )  ——>  hsl(  54,  99%,  71% )  =  $yella_4l
$green   : #16c98d  =  hsl( 160,  80%,  44% )  ——>  hsl( 160,  80%,  45% )  =  $green_1d
$teal    : #0fdebd  =  hsl( 170,  87%,  46% )  ——>  hsl( 170,  87%,  45% )  =  $teal_1d
$lpblue  : #297cbb  =  hsl( 206,  64%,  45% )  ——>  hsl( 206,  69%,  45% )  =  $blue_1d
$linkblue: #288ad6  =  hsl( 206,  69%,  50% )  ——>  hsl( 206,  69%,  50% )  =  $blue
$darkblue: #142b44  =  hsl( 211,  55%,  17% )  ——>  hsl( 206,  69%,  17% )  =  $blue_5d
$navblue : #1d508d  =  hsl( 213,  66%,  33% )  ——>  hsl( 206,  69%,  33% )  =  $blue_3d
$plum    : #bf538d  =  hsl( 328,  46%,  54% )  ——>  hsl( 328,  46%,  54% )  =  $plum_1l

В данном примере шкала уровней отклонения светлости от базового цвета равна⁠: ±33, ±21, ±17, ±12, ±5 (4)⁠. Для максимальной релевантности брендовых цветов и новой палитры на уровне 1l отклонение по светлости равно +4⁠, а на уровне 1d — -5.

Результат наших манипуляций представлен ниже⁠. Это «живой» HTML и CSS⁠, тут можно поинспектировать, исследовать значения цветов и их разницу⁠.

5L
4L
3L
2L
1L
red
1D
2D
3D
4D
5D
5L
4L
3L
2L
1L
orange
1D
2D
3D
4D
5D
5L
4L
3L
2L
1L
yella
1D
2D
3D
4D
5D
5L
4L
3L
2L
1L
green
1D
2D
3D
4D
5D
5L
4L
3L
2L
1L
teal
1D
2D
3D
4D
5D
5L
4L
3L
2L
1L
blue
1D
2D
3D
4D
5D
5L
4L
3L
2L
1L
plum
1D
2D
3D
4D
5D
5L
4L
3L
2L
1L
gray
1D
2D
3D
4D
5D

Серой рамкой обозначены базовые цвета⁠, т.е. те цвета⁠, которые являются основой для всех остальных (производных) цветов палитры.

Маркером (⁠белой точкой⁠) указаны брендовые цвета⁠. Рядом с маркером⁠, для сравнения⁠, имеется область исходного цвета из палитры дизайнера. Для наглядности⁠, ниже представлен увеличенный участок палитры, с цветами имеющими отличие от исходных⁠.

Сравнение исходной и новой палитры
Сравнение исходной и новой палитры

Такие расхождения — следствие допущений принятых при построении палитры. При работе с синими я приравнял их параметры Hue и Saturation⁠, а при работе с цветами близкими по светлоте⁠, их светлота приводилась к единому значению, всё это повлияло на конечный результат.

Чем меньше цветов одного тона будет в исходной палитре и чем больше будет цветов равных по светлоте⁠, тем выше будет релевантность исходной и новой палитры.

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

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

Для изучения материала рекомендую проанализировать палитры других сайтов: gov.uk⁠, disqus.com⁠, linkedin.com

Используйте качественные палитры!

Sass автоматически конвертирует hsl в rgb. И делает это практически правильно. На момент написания статьи bug имеет статус «open»⁠.

Вместо заключения — Задолба!ли — Говорите поярче⁠.