Формати задання кольорів функцією rgb() та шістнадцятковим значенням були представлені ще в перших версіях CSS приблизно у 1996 році. Очевидно, що час не стоїть на місці та CSS далеко розвинувся з тих часів. Попри це, чомусь, багато веброзробників та вебдизайнерів вперто продовжують використовувати цей застарілий, обмежений та нелюдський формат кольору по цей день.
Примітка: Що таке колірний простір
Зображення та кольори, які ми бачимо на екранах, представлені у вигляді чисел, які кодують кольорову інформацію. Колірний простір — це спосіб організації цих чисел, який визначає, як кольори інтерпретуються та відображаються.
Подібно до того, як ми використовуємо координатну систему для визначення положення точки на площині, колірні простори допомагають нам визначити, який колір має певні числові значення.
Наприклад, якщо у мене є камера, яка знімає в довільному «Колірному просторі A», все, що я знімаю, що має значення кольору та/або яскравості, що перевищують межі, які може визначити цей простір, не буде точно зафіксовано. З цими «поза межами» значень можна працювати різними способами (деякі візуально приємніші, ніж інші), але їх неможливо точно охопити, як вони виглядають у реальному світі.
Те саме стосується пристрою відображення, призначеного для відтворення «Колірного простору B» — будь-який колір або значення яскравості, збережене в цифровому зображенні, яке виходить за межі «Колірного простору B», не може бути точно показано на цьому конкретному екрані.
В обох випадках більші колірні простори означають, що більший діапазон кольорів можна точно зафіксувати та/або відтворити.
Проблеми rgb та hex
Обмежена кількість кольорів
RGB (Red, Green, Blue) - це один з найпоширеніших колірних просторів, де кожен колір представлений числами від 0 до 255, що відповідають інтенсивності червоного, зеленого та синього каналів.
Його було створено у 1996 році, він відповідає потребам тих часів та є одним з найменших кольорових просторів (охоплює найменшу кількість кольорів).
RGB може містити в собі приблизно 16.7 мільйонів кольорів. До прикладу сучасний Apple Pro Display здатен відображати понад 1000 мільйонів кольорів (за заявами виробника).
Не дружній для людей
Метод визначення кольору в RGB це поєднання червоного (R), зеленого (G) та синього (B) каналів. Легко зрозуміти чому модель була саме такою — це відсоток яскравості для кожного субпікселя на дисплеї.
Це зручно для машини, але вкрай не зручно для людини. Чи можете ви легко уявити приблизний результат з формули 35% червоного 100% зеленого + 84% синього?
Не дружній для веброзробки
Шлях визначення кольору RGB не відповідає тенденціям вебдизайну. Дизайнери часто використовують систему кольорів, що складається з одного або кількох основних кольорів, на основі яких будуються всі компоненти.
Наприклад картка профілю Друкарні. Є один основний колір — зелений. Він же брендовий колір всього вебсайту. Фон картки це той же основний колір, але світліший, а лінії в картці це основний колір, але більш насичений. Кнопки отримують основний колір, але при наведенні це блідіша версія основного кольору.
Тобто для створення цього компоненту потрібно оперувати такими характеристиками кольору як його відтінок, яскравість та насиченість. І аж ніяк не “червоність”, “зеленість” чи “синість”.
Hsl це розв'язання всіх проблем?
CSS функція hsl() була представлена у 1999 році та пропонує зручніший шлях визначення кольорів на основі відтінку (Hue), насиченості (Saturation) та яскравості (Lightness). А відсоток яскравості для RGB субпікселів вираховується автоматично пристроєм.
Він привносить принципово новий та зручніший для веброзробки спосіб визначення кольорів. З hsl() верстка компонента картки профілю друкарні може виглядати так:
.card {
background: hsl(
var(--theme-hue)
var(--theme-saturation)
calc( var(--theme-saturation) + 15%) /* збільшуємо яскравість */
);
border-color: hsl(
var(--theme-hue)
calc( var(--theme-saturation) + 15%) /* збільшуємо насиченість */
var(--theme-lightness)
)
}
Крім цього така система дозволяє легко будувати варіації компонентів змінюючи відтінок та не змінюючи інші складові.
Наприклад кольорові спливні сповіщення. Завдяки hsl() ви можете сконструювати компонент таким чином, щоб він приймав лише одну змінну — базовий відтінок, та будував всі похідні (світліші, темніші) кольори від нього:
[role="alert"] {
border-color: hsl(var(--hue) 80% 50%);
background-color: hsl(var(--hue) 50% 85% / 0.5);
color: hsl(var(--hue) 100% 20%);
}
<div role="alert" style="--hue: 0">Помилка</div>
<div role="alert" style="--hue: 40">Попередження</div>
<div role="alert" style="--hue: 210">Повідомлення</div>
<div role="alert" style="--hue: 130">Успішно</div>
Подібний код легше читати та розуміти. Людина може легко уявити приблизний результат від формули “Синій - 30% насиченості”. А вебдизайн можна будувати більш оптимально вираховуючи похідні кольори замість визначення десятка варіацій в rgb чи hex форматах.
Недоліки HSL
Кольоровий простір HSL може містити приблизно таку ж кількість кольорів що й RGB. А це, як описано вище не дуже багато.
HSL також не враховує специфіки людського ока. Річ в тім, що людина сприймає різні кольори по різному. З цієї причини, два кольори, які технічно мають ідентичну насиченість та яскравість можуть відчуватись яскравішими чи темнішими залежно від відтінку.
Зверніть увагу наскільки простіше прочитати білий текст на синьому фоні, а ніж на жовтому.
LCH це розв'язання всіх проблем?
Функція lch() це наступна ітерація покращень для роботи з кольорами в CSS. ЇЇ було представлено у 2021 році.
Функція lch() дозволяє задавати кольори в просторі LCH — яскравість (lightness), кольоровість (chroma) та відтінок (hue).
Параметри приблизно відповідають HSL, але є деякі відмінності.
У HSL насиченість становить 0-100 відсотків. Проте в LCH кольоровість теоретично необмежена. LCH розроблений таким чином, щоб мати можливість представляти весь спектр людського зору, і не всі ці кольори можуть відображатися на екранах, навіть на найсучасніших. Якщо ви вкажете колір який неможливо відобразити на дисплеї його буде зменшено до найбільш відповідного підтримуваного кольору.
Іншою важливою відмінністю від HSL є те, що LCH намагається враховувати специфіку людського ока. Тобто два кольори з однаковою кольоровістю та яскравістю будуть сприйматись однаково людиною.
Недоліки LCH
Формули вирахування кольорів в LCH не є ідеальними. Наприклад зміна насиченості може впливати на те як людина сприймає яскравість кольору. Крім того, є певна несиметричність в розподіленні кольорів.
OkLCH це розв'язання всіх проблем?
oklch() (optimized LCH) є вдосконаленою версією LCH.
Приймає такі ж параметри, але внутрішні формули обрахування кольорів дещо виправлені, щоб усунути недоліки LCH.
На момент написання цього довгочиту OkLCH це найдосконаліша система визначення кольору в CSS:
Вона дозволяє визначити набагато більше кольорів ніж rgb.
Вона оперує зрозумілими людині концепціями як то відтінок, кольоровість та яскравість.
Її парадигма відповідає парадигмі вебдизайну та дозволяє легко вираховувати похідні кольори від основного.
Має непогану підтримку браузерами.
Крім цього, сучасні інструменти збірки вміють автоматично вираховувати найближчий відповідний колір в rgb для старих браузерів
body {
background: oklch(40.1% 0.123 21.57);
}
/* Може бути зкомпільовано у */
body {
background: #7d2429;
background: lab(29.2361% 39.2634 19.9983);
}
Підсумок
Вебтехнології та браузери пройшли величезний шлях від примітивного RGB до складного OkLCH. І у першого немає жодних переваг перед останнім.
Бонус
З приходом у CSS Relative Color Syntax з’явиться ще одна причина використовувати сучасні системи кольорів замість примітивного RGB.
div {
/* Взяти колір зі змінної --theme-color,
розбити його на складові lightness, chroma, hue.
Сформувати новий колір де hue залишаєтсья без змін,
chroma зменшено на 20%,
lightness зменшено на 30%.
В результаті фон буде майже чорним з легким відтінком кольору, що був переданий у --theme-color.
*/
background: oklch(from var(--theme-color) calc(l - 0.3) calc(c - 0.2) h)
}