<commit_before>---
layout: post
title:  "Перестаньте использовать RGB цвета"
ref: "stop-rgb"
lang: "ru"
published: true
description: "Перестаньте использовать RGB цвета и начните использовать HSL"
excerpt: ""
---

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

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

В начале 19го века <NAME>нг и <NAME>ельмгольц [разработали теорию][yh-theory], согласно которой человеческий глаз
способен различать цвет благодаря наличию трех типов рецепторов, каждый из которых имеет разную кривую
возбуждения в зависимости от длинны световой волны. А все промежуточные цвета получались как комбинации.

![Чувствительность рецепторов][yh-theory-img]

На основе этой теории появилась аддитивная цветовая модель [RGB][rgb]. Аббревиатура использует заглавные
буквы трех цветов (**r**ed, **g**reen, **b**lue), которые в комбинации дают достаточно большой
(но все же не полный) охват цветов.

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

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

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

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

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

![HEX][hex-img]

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

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

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

```css
#00FE00
```

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

```css
#faff10
```

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

```css
#E9967A
```

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

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

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

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

![Material design colors][material-img]

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

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

<span class="color-entity" style="background:#a70606; color: #fff">#A70606</span>

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

<span class="color-entity" style="background:#8d2020; color: #fff">#8D2020</span>

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

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

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

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

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

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

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

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

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

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

![HSL cylinder][hsl-img]

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

![HSL line][line-img]

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

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

```css
hsl(61, 100%, 53%)
```

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

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

![Yellow color lightness][yellow-img]

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

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

```css
hsl(15, 72%, 70%)
```

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

<span class="color-entity" style="background:hsl(15, 72%, 70%); color: #000">hsl(15, 72%, 70%)</span>

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

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

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

```html
<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>
```

Результат:
<div>
  <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>
  <br/>
  <br/>
</div>


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

```html
<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>
```

Результат:
<div style="display: flex;">
  <style>
    .alert {
      --saturation: 100%;
      --lightness: 65%;
      width: 150px;
      height: 30px;
      padding: 5px 10px;
      text-align: center;
      margin-right: 10px;

      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>
  <br/>
  <br/>
</div>

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

```css
<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>
```
<div style="display: flex;">
  <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 {
      width: 100%;
      height: 40px;
      animation: color-change 3s infinite;
    }
  </style>

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

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

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


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

Конечно есть. Хотя модель HSL и предоставляет дает много удобств, она является той же самой моделью,
что и RGB, но в других координатах. Современные дисплеи могут показывать гораздо больше цветов
в более широких диапазонах. И когда нибудь [браузеры смогут работать с этими цветами][low].
<commit_msg>typos<commit_after>---
layout: post
title:  "Перестаньте использовать RGB цвета"
ref: "stop-rgb"
lang: "ru"
published: true
description: "Перестаньте использовать RGB цвета и начните использовать HSL"
excerpt: ""
---

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

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

В начале 19го века <NAME> и <NAME> [разработали теорию][yh-theory], согласно которой человеческий глаз
способен различать цвет благодаря наличию трех типов рецепторов, каждый из которых имеет разную кривую
возбуждения в зависимости от длинны световой волны. А все промежуточные цвета получались как комбинации.

![Чувствительность рецепторов][yh-theory-img]

На основе этой теории появилась аддитивная цветовая модель [RGB][rgb]. Аббревиатура использует заглавные
буквы трех цветов (**r**ed, **g**reen, **b**lue), которые в комбинации дают достаточно большой
(но все же не полный) охват цветов.

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

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

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

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

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

![HEX][hex-img]

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

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

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

```css
#00FE00
```

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

```css
#faff10
```

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

```css
#E9967A
```

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

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

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

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

![Material design colors][material-img]

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

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

<span class="color-entity" style="background:#a70606; color: #fff">#A70606</span>

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

<span class="color-entity" style="background:#8d2020; color: #fff">#8D2020</span>

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

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

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

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

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

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

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

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

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

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

![HSL cylinder][hsl-img]

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

![HSL line][line-img]

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

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

```css
hsl(61, 100%, 53%)
```

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

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

![Yellow color lightness][yellow-img]

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

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

```css
hsl(15, 72%, 70%)
```

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

<span class="color-entity" style="background:hsl(15, 72%, 70%); color: #000">hsl(15, 72%, 70%)</span>

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

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

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

```html
<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>
```

Результат:
<div>
  <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>
  <br/>
  <br/>
</div>


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

```html
<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>
```

Результат:
<div style="display: flex;">
  <style>
    .alert {
      --saturation: 100%;
      --lightness: 65%;
      width: 150px;
      height: 30px;
      padding: 5px 10px;
      text-align: center;
      margin-right: 10px;

      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>
  <br/>
  <br/>
</div>

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

```css
<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>
```
<div style="display: flex;">
  <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 {
      width: 100%;
      height: 40px;
      animation: color-change 3s infinite;
    }
  </style>

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

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

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


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

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

{'fraction_non_alphanumeric': 0.11034627712679312, 'fraction_numerical': 0.02553728127791498, 'mean_word_length': 4.231445849367785, 'pattern_counts': {'":': 0, '<': 117, '<?xml version=': 0, '>': 119, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5927121', 'n_tokens_mistral': 8209, 'n_tokens_neox': 8745, 'n_words': 2259}