<-- home

Перестаньте использовать RGB цвета

English version

TL;DR rgb цвета неудобны, hsl проще читать и модифицировать

Немного истории

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

Чувствительность рецепторов

На основе этой теории появилась аддитивная цветовая модель RGB. Аббревиатура использует заглавные буквы трех цветов (red, green, blue), которые в комбинации дают достаточно большой (но все же не полный) охват цветов.

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

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

Чтобы стандартизировать единый способ представления изображение Microsoft и HP в 1996м году создают формат sRGB, который так же попадает в спецификацию W3C, и позже становится стандартом для указания цвета в CSS.

Использование в CSS

Изначально в HTML использовался шестнадцатеричный (HEX) способ записи цветов. Почему именно шестнадцатеричный? Дело в том, как хранится информация в современных компьютерах. Каждый байт может хранить число от 0 до FF в шестнадцатеричном формате.

HEX

Для большего удобства (если это можно назвать удобством) в CSS добавили возможность использовать цветовую функцию rgb, в которой каждое значение можно задавать десятеричным числом.

Где проблема?

Какой это цвет?

#00FE00

Конечно ярко-зеленый! А вот этот?

#faff10

Желтый. Угадали? Я тоже, ведь годы смотрю на эти цифры и могу понять. А этот сможете представить смотря на цифры?

#E9967A

Я — нет. А это стандартный браузерный цвет, который называется DarkSalmon.

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

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

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

Material design colors

Отсутствие гибкости

Допустим обозначенные проблемы с чтением кода для вас не стоят. Тут мы сталкиваемся с тем, что любые относительные изменения цвета невозможны без инструментов для преобразования. Поясню на примере. Допустим, у нас есть цвет:

#A70606

Как сделать его немного темнее? Или немного светлее? А, может, при наведении мы хотим сделать его менее насыщенным? Например таким:

#8D2020

Ответ: используя инструмент вашего редактора. Или, если нужно сделать подобное динамически, то используя библиотеку.

Конечно, вы можете попытаться использоваться функцию calc внутри rgb в CSS. Ну, удачи с этим!

Или такой вопрос: какой цвет текста будет более читабелен на фоне 9AAAFE? Конечно, можно заняться математикой в уме и понять, что черный цвет будет чуть лучше белого.

Все эти вопросы следствие того факта, что модель RGB была создана для воспроизведения цвета экранами и принтерами, а не для чтения человеком.

HSL во спасение!

Согласно википедии

HSL (от англ. hue, saturation, lightness) — цветовая модель, в которой цветовыми координатами являются тон, насыщенность и светлота.

Модель была изобретена Джоржем Валенси в 1938м году для кодирования телесигнала, который могли бы воспринимать как цветные, так и ЧБ приемники.

Три компонента, которые дают определение цвета в модели HSL:

  • Hue — тон, определяет цвет, число от 0° до 360°
  • Saturation — насыщенность, от 0 — бесцветный до 1 — полноцветный
  • Lightness — светлость, от 0 — черный до 1 — белый

HSL cylinder

Насыщенность и светлота просты для понимания. С тоном немного сложнее, нужно помнить про граничные цвета. Тут нам может помочь известная с детства мнемоническая фраза “Каждый охотник желает знать, где сидит фазан”.

HSL line

Красный цвет на нуле (и 360, так как это окружность). Голубой на 180°. Остальные цвета распределены достаточно равномерно, с интервалом ~60°, не считая оранжевого.

Давайте теперь вернемся к цветам, которые обсуждали ранее. Желтый цвет #FAFF10 в HSL будет выглядеть так (CSS синтаксис):

hsl(61, 100%, 53%)

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

Со значением светлости чуть сложнее. Когда значение 0%, то цвет полностью черный, а при значении 100% получаем полностью белый. Однако значение 50% дает нужный чистый цвет. Вот палитра нашего цвета (H = 61, S = 100%) с изменением светлости от 0% до 10% (голубой фон для выделения белого):

Yellow color lightness

И теперь глядя на hsl(61, 100%, 53%) можно понять, что это насыщенный желтый цвет без всяких инструментов.

Попробуем с другим цветом. Упомянутый выше DarkSalmon в HSL выглядит так

hsl(15, 72%, 70%)

То есть красный со смещением в оранжевый, немного тусклый и белесый.

hsl(15, 72%, 70%)

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

Генерация цветов

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

<style>
  .h-btn {
    --hue: 220;
    --saturation: 100%;

    background: hsl(var(--hue), var(--saturation), 65%);
  }
  .h-btn:hover {
    background: hsl(var(--hue), var(--saturation), 50%);
  }
  .h-btn:disabled {
    background: hsl(var(--hue), var(--saturation), 80%);
  }
</style>

<button class="h-btn">Hover me</button>
<button class="h-btn" disabled>Disabled</button>

Результат:



Или наоборот, зафиксировать насыщенность и светлость и менять тон.

<style>
  .alert {
    --saturation: 100%;
    --lightness: 65%;

    background: hsl(35, var(--saturation), var(--lightness));
  }
  .alert--danger {
    background: hsl(0, var(--saturation), var(--lightness));
  }
  .alert--info {
    background: hsl(180, var(--saturation), var(--lightness));
  }
</style>

<div class="alert">Важно!</div>
<div class="alert alert--danger">Опасно!</div>
<div class="alert alert--info">Интересно!</div>

Результат:

Важно!
Опасно!
Интересно!


Анимации с пульсирующим цветом:

<style>
  @keyframes color-change {
    0% { background-color: hsl(210, 100%, 50%); }
    50% { background-color: hsl(210, 100%, 90%); }
    100% { background-color: hsl(210, 100%, 50%); }
  }

  .pulse {
    animation: color-change 3s infinite;
  }
</style>

<div class="pulse"></div>


Поддержка браузерами

Цветовые функции hsl и hsla поддерживаются всеми современными браузерами. Поддержка Internet Explorer начинается с девятой версии.

Есть ли недостатки?

Конечно, есть. Хотя модель HSL и предоставляет много удобств, она является той же самой моделью, что и RGB, но в других координатах. Современные дисплеи могут показывать гораздо больше цветов в более широких диапазонах. И когда нибудь браузеры смогут работать с этими цветами.

HEX коды меньше размером, чем hsl функции. Но если вас волнуют такого рода оптимизации, то вы скорее всего уже используете минификаторы, например postcss-colormin.

Comments