Построение цветовой схемы

Общий обзор того, как создать динамическую и настраиваемую цветовую схему.

В этом посте я хочу поделиться своими мыслями о способах управления несколькими цветовыми схемами в CSS. Попробуйте демо-версию .

Демо

Если вам удобнее видео, вот версия этого поста на YouTube:

Обзор

Мы создадим доступную цветовую систему с настраиваемыми свойствами и calc() , чтобы веб-страница адаптировалась к предпочтениям пользователя, сохраняя при этом минимальные сложности в процессе создания. Мы начнем с базового фирменного цвета и построим на его основе систему вариантов: 2 цвета текста, 4 цвета поверхности и соответствующую тень.

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

Бренд

Часто фирменный цвет уже установлен и представлен в шестнадцатеричном формате или в формате RGB . В этом задании по графическому интерфейсу пользователя базовый фирменный цвет — #0af . Во-первых, для этой цветовой системы шестнадцатеричное значение необходимо преобразовать в формат HSL .

* {
  --brand: #0af;
  --brand: hsl(200 100% 50%);
}

Для реализации концепции затемнения или осветления фирменного цвета, скажем, на 20%, необходимо выделить 3 канала значения цвета HSL в отдельные пользовательские свойства, следующим образом:

* {
  --brand-hue: 200;
  --brand-saturation: 100%;
  --brand-lightness: 50%;
}

В CSS можно выполнять математические операции над этими цветовыми свойствами, например calc(var(--brand-lightness) - 20%) чтобы уменьшить значение яркости на 20%. Это основополагающий принцип построения цветовой схемы, поскольку CSS может сохранять все цвета в одном цветовом семействе, регулируя значения насыщенности и яркости в HSL.

Светлая тема

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

Предварительный просмотр результатов работы над световой темой.

Бренд

Начиная с фирменного цвета, он перестраивается путем заключения пользовательских свойств --brand-hue , --brand-saturation и --brand-lightness в скобки функции hsl () , без каких-либо вычислений:

* {
  --brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
}

Цвета текста

Далее, основные элементы цветовой схемы — это цвета текста. В светлой цветовой гамме текст должен быть очень темным. Обратите внимание, что светлость следующих цветов низкая, значительно ниже 50%.

* {
  --text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
  --text2-light: hsl(var(--brand-hue) 30% 30%);
}

--text1-light , поскольку цвет очень темный (10%), сохраняет высокую насыщенность (100%), чтобы фирменный цвет все еще просвечивал сквозь темно-синий.

--text2-light , он не такой тёмный, как первый цвет, что хорошо, поскольку это вторичный цвет, и он также гораздо менее насыщенный.

Цвета поверхности

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

* {
  --surface1-light: hsl(var(--brand-hue) 25% 90%);
  --surface2-light: hsl(var(--brand-hue) 20% 99%);
  --surface3-light: hsl(var(--brand-hue) 20% 92%);
  --surface4-light: hsl(var(--brand-hue) 20% 85%);
}

Было создано 4 варианта цвета поверхности, поскольку декоративные цвета, как правило, требуют больше вариаций для интерактивных моментов, таких как :focus или :hover , или для создания эффекта слоев бумаги. В таких сценариях удобно переключать --surface2-light при наведении курсора на --surface3-light , чтобы при наведении курсора увеличивался контраст (с 99% до 92% яркости, что делает поверхность темнее).

Тени

Тени в рамках цветовой схемы — это нечто большее, чем просто тени, они придают эффекту реалистичность и помогают ему выделиться на фоне неестественных теней на черном фоне. Для этого цвет тени будет задаваться пользовательским свойством «оттенок», быть слегка насыщенным этим оттенком, но при этом оставаться очень темным. По сути, создается очень темная, слегка голубоватая тень.

* {
  --surface-shadow-light: var(--brand-hue) 10% 20%;
  --shadow-strength-light: .02;
}

--surface-shadow-light не заключен в функцию hsl. Это связано с тем, что значение --shadow-strength будет использоваться для создания некоторой прозрачности, а CSS нужны эти части для выполнения вычислений. Перейдите к разделу о тенях, чтобы узнать больше.

Светлые цвета все вместе

Нет необходимости искать, как создаются те или иные светлые оттенки, все они находятся в одном месте в CSS.

* {
  --brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
  --text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
  --text2-light: hsl(var(--brand-hue) 30% 30%);
  --surface1-light: hsl(var(--brand-hue) 25% 90%);
  --surface2-light: hsl(var(--brand-hue) 20% 99%);
  --surface3-light: hsl(var(--brand-hue) 20% 92%);
  --surface4-light: hsl(var(--brand-hue) 20% 85%);
  --surface-shadow-light: var(--brand-hue) 10% calc(var(--brand-lightness) / 5);
  --shadow-strength-light: .02;
}
Скриншот, на котором все светлые цвета собраны вместе.
Песочница на CodePen

Темная тема

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

  1. Пользователи, как правило, не будут иметь доступа к этой теме при её использовании, поэтому тестируйте в темноте.
  2. Цвета следует сделать менее насыщенными, чтобы избежать вибрации на экране из-за чрезмерной интенсивности.

Предварительный просмотр конечного результата использования темной темы.

Бренд

В светлой теме используются значения 3 цветовых каналов HSL без изменений, в темной теме — нет. Насыщенность уменьшена вдвое, а яркость снижена на относительные 50%.

* {
  --brand-dark: hsl(
    var(--brand-hue)
    calc(var(--brand-saturation) / 2)
    calc(var(--brand-lightness) / 1.5)
  );
}

Цвета текста

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

* {
  --text1-dark: hsl(var(--brand-hue) 15% 85%);
  --text2-dark: hsl(var(--brand-hue) 5% 65%);
}

Цвета поверхности

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

* {
  --surface1-dark: hsl(var(--brand-hue) 10% 10%);
  --surface2-dark: hsl(var(--brand-hue) 10% 15%);
  --surface3-dark: hsl(var(--brand-hue) 5%  20%);
  --surface4-dark: hsl(var(--brand-hue) 5% 25%);
}

Тени

В темной теме тени очень трудно разглядеть. Это логично, поскольку трудно затемнить то, что и так достаточно темное. Вот тут-то и пригодится --shadow-strength-dark , позволяющий затемнить тени, изменив всего одну переменную.

* {
  --surface-shadow-dark: var(--brand-hue) 50% 3%;
  --shadow-strength-dark: .8;
}

Также обратите внимание на насыщенность тени. Вы можете различить цвет, когда смотрите на интерфейс? Попробуйте уменьшить насыщенность в инструментах разработчика, какой вариант вам больше нравится?!

Все темные цвета вместе

* {
  --brand-dark: hsl(var(--brand-hue) calc(var(--brand-saturation) / 2) calc(var(--brand-lightness) / 1.5));
  --text1-dark: hsl(var(--brand-hue) 15% 85%);
  --text2-dark: hsl(var(--brand-hue) 5% 65%);
  --surface1-dark: hsl(var(--brand-hue) 10% 10%);
  --surface2-dark: hsl(var(--brand-hue) 10% 15%);
  --surface3-dark: hsl(var(--brand-hue) 5%  20%);
  --surface4-dark: hsl(var(--brand-hue) 5% 25%);
  --surface-shadow-dark: var(--brand-hue) 50% 3%;
  --shadow-strength-dark: .8;
}
скриншот, на котором все темные цвета собраны вместе
Песочница на CodePen

Темная тема

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

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

Бренд

* {
  --brand-dim: hsl(
    var(--brand-hue)
    calc(var(--brand-saturation) / 1.25)
    calc(var(--brand-lightness) / 1.25)
  );
}

Цвета текста

* {
  --text1-dim: hsl(var(--brand-hue) 15% 75%);
  --text2-dim: hsl(var(--brand-hue) 10% 61%);
}

Цвета поверхности

* {
  --surface1-dim: hsl(var(--brand-hue) 10% 20%);
  --surface2-dim: hsl(var(--brand-hue) 10% 25%);
  --surface3-dim: hsl(var(--brand-hue) 5%  30%);
  --surface4-dim: hsl(var(--brand-hue) 5% 35%);
}

Тени

* {
  --surface-shadow-dim: var(--brand-hue) 30% 13%;
  --shadow-strength-dim: .2;
}

Тусклые цвета все вместе

* {
  --brand-dim: hsl(var(--brand-hue) calc(var(--brand-saturation) / 1.25) calc(var(--brand-lightness) / 1.25));
  --text1-dim: hsl(var(--brand-hue) 15% 75%);
  --text2-dim: hsl(var(--brand-hue) 10% 61%);
  --surface1-dim: hsl(var(--brand-hue) 10% 20%);
  --surface2-dim: hsl(var(--brand-hue) 10% 25%);
  --surface3-dim: hsl(var(--brand-hue) 5%  30%);
  --surface4-dim: hsl(var(--brand-hue) 5% 35%);
  --surface-shadow-dim: var(--brand-hue) 30% 13%;
  --shadow-strength-dim: .2;
}
скриншот, на котором все тусклые цвета собраны вместе
Песочница на CodePen

Доступные цвета

Обратите внимание, что наименьшая яркость в темном наборе цветов текста составляет 65%, а наибольшая яркость в темных поверхностях — 25%. Это означает, что между ними есть 40% запаса по яркости. В светлой теме запас составляет 55%. Поддержание разницы в яркости между цветами текста и поверхностей на уровне 40-50% помогает сохранить высокий коэффициент контрастности цветов, а также является тонким инструментом для корректировки в случае низких показателей.

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

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

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

.surface1 {
  background-color: var(--surface1);
  color: var(--text2);
}

.surface2 {
  background-color: var(--surface2);
  color: var(--text2);
}

.surface3 {
  background-color: var(--surface3);
  color: var(--text1);
}

.surface4 {
  background-color: var(--surface4);
  color: var(--text1);
}
Скриншот тусклой поверхности и сочетаний текста.
Скриншот затемненной поверхности и сочетаний текста, полученный с помощью VisBug.

Рад Шэдоу

В темах используется вспомогательный класс под названием .rad-shadow . Эта тень была сгенерирована с помощью инструмента Smooth Shadow , который мне очень нравится. Я взял сгенерированный фрагмент кода и настроил его, добавив свои собственные цвета и параметры прозрачности. Причина этого заключалась в создании тени, которую я мог бы регулировать в рамках каждой цветовой схемы.

каждая тень рядом друг с другом

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

:root {
  --surface-shadow-light: var(--brand-hue) 10% 20%;
  --shadow-strength-light: .02;
}

.rad-shadow {
  box-shadow:
    0 2.8px 2.2px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
    0 6.7px 5.3px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .01)),
    0 12.5px 10px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
    0 22.3px 17.9px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
    0 41.8px 33.4px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
    0 100px 80px hsl(var(--surface-shadow) / var(--shadow-strength))
  ;
}

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

Использование цветовых схем

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

Для этого использование цветовой схемы должно осуществляться исключительно через общие пользовательские свойства, которые мы определим чуть позже. Таким образом, пользователям, использующим переменные дизайна, не нужно будет беспокоиться о том, какая цветовая схема установлена ​​в данный момент, им нужно будет использовать только цвета поверхности и текста. Вместо color: var(--text1-light) используйте color: var(--text1) . Все изменения и корректировка цветов выполняются на гораздо более высоком уровне в CSS.

Рассмотрим стили соединения светлой темы в следующем блоке кода, которые связывают универсальное пользовательское свойство с цветом, специфичным для светлой темы. Теперь все использования var(--brand) будут использовать цвет светлой темы.

Светлая тема (автоматическая)

:root {
  color-scheme: light;
  --brand: var(--brand-light);
  --text1: var(--text1-light);
  --text2: var(--text2-light);
  --surface1: var(--surface1-light);
  --surface2: var(--surface2-light);
  --surface3: var(--surface3-light);
  --surface4: var(--surface4-light);
  --surface-shadow: var(--surface-shadow-light);
  --shadow-strength: var(--shadow-strength-light);
}

Теперь на сайте используется светлая тема оформления. Это очень приятный и успешный момент! Давайте повторим ещё несколько таких моментов, используя наши предопределенные цвета в других цветовых схемах.

Темная тема (автоматическая)

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;

    --brand: var(--brand-dark);
    --text1: var(--text1-dark);
    --text2: var(--text2-dark);
    --surface1: var(--surface1-dark);
    --surface2: var(--surface2-dark);
    --surface3: var(--surface3-dark);
    --surface4: var(--surface4-dark);
    --surface-shadow: var(--surface-shadow-dark);
    --shadow-strength: var(--shadow-strength-dark);
  }
}

Светлая тема

[color-scheme="light"] {
  color-scheme: light;

  --brand: var(--brand-light);
  --text1: var(--text1-light);
  --text2: var(--text2-light);
  --surface1: var(--surface1-light);
  --surface2: var(--surface2-light);
  --surface3: var(--surface3-light);
  --surface4: var(--surface4-light);
  --surface-shadow: var(--surface-shadow-light);
  --shadow-strength: var(--shadow-strength-light);
}

Темная тема

[color-scheme="dark"] {
  color-scheme: dark;

  --brand: var(--brand-dark);
  --text1: var(--text1-dark);
  --text2: var(--text2-dark);
  --surface1: var(--surface1-dark);
  --surface2: var(--surface2-dark);
  --surface3: var(--surface3-dark);
  --surface4: var(--surface4-dark);
  --surface-shadow: var(--surface-shadow-dark);
  --shadow-strength: var(--shadow-strength-dark);
}

Темная тема

[color-scheme="dim"] {
  color-scheme: dark;

  --brand: var(--brand-dim);
  --text1: var(--text1-dim);
  --text2: var(--text2-dim);
  --surface1: var(--surface1-dim);
  --surface2: var(--surface2-dim);
  --surface3: var(--surface3-dim);
  --surface4: var(--surface4-dim);
  --surface-shadow: var(--surface-shadow-dim);
  --shadow-strength: var(--shadow-strength-dim);
}

На данном этапе авторы могут свободно использовать предоставленные общие цветовые схемы по мере необходимости и им больше никогда не придется беспокоиться о темах оформления.

Заключение

Теперь, когда вы знаете, как я это сделал, как бы вы поступили так же?! 🙂

Давайте разнообразим наши подходы и изучим все способы разработки веб-приложений. Создайте Codepen или разместите свою собственную демо-версию, напишите мне в Твиттере, и я добавлю её в раздел «Ремиксы сообщества» ниже.

Источник

Ремиксы от сообщества - @chris-kruining добавил ползунок оттенка, цвета статуса и режимы контрастности для no-preference , more и less : демо .