OKLCH - новые цвета в CSS
Недавно релизнулся Tailwind CSS v4.0, где они написали, что поменяли все цвета с RGB на OKLCH. Лично я ничего не знал об OKLCH, поэтому решил немного разобраться, что это за «зверь».
Если очень кратко, то OKLCH — это цветовая модель, которая предназначена для более широкого охвата цветов, чем привычный sRGB. Модель OKLCH применяется для мониторов и проекторов, которые поддерживают устройства DCI-P3. Сейчас таких устройств не очень много, потому что это в основном мониторы Apple. Нужно отметить, что DCI-P3 и OKLCH очень молодые разработки: первые устройства это 2015 год, а OKLCH вообще опубликован только в 2021 году, а его поддержка в браузерах — это 2023-2024 год. То есть OKLCH, если кратко — слишком молода, чтобы ей вообще пользоваться.
При этом, сама по себе модель OKLCH лучше подходит для будущих устройств. Может лет через 5-10, когда мониторы и ноутбуки будут уже поддерживать DCI-P3, тогда модель OKLCH покажет себя во всей красе (в буквальном смысле слова). Поэтому вполне возможно, что дизайнеры начнут использовать OKLCH в своих работах.
Чтобы понять отличие OKLCH от RGB, нужно немного углубиться в теорию цвета. Поэтому приведу небольшой ликбез.
Как мы видим

Наше цветовое зрение работает через рецепторы (колбочки), которые воспринимают свой цвет. Есть рецепторы для красного, зеленого и синего цвета. Путем смешения этих опорных цветов в разных пропорциях, мы и видим все возможные оттенки. С точки зрения физики, рецепторы реагируют на разные электромагнитные колебания примерно от 380нм до 780нм, но чувствительность рецепторов разная. Например чувствительность к зеленому цвету у нас выше, чем к красному и синему. То есть восприятие цветов у нас нелинейно.
Чтобы описать это математически были проведены разные измерения и была придумана эталонная модель CIE XYZ, которая охватывает все цвета, которые может воспринять человек. Если это всё перевести в одну плоскость, то получится такая диаграмма:
Числа вокруг цветового поля — это частоты колебаний. Обратие внимание, что например между 460нм и 480нм (разница 20нм) буквально 2 деления шкалы, а между 480нм и 500нм (такая же разница в 20нм) уже 8 делений шкалы. То есть цветовая шкала очень нелинейна.
Модели печати CMYK/CMY
Модель CIE XYZ идеальна, поскольку описывает все цвета, которые можно увидеть глазами. Но цвета, которые встречаются в природе, не всегда можно воспроизвести на устройствах.
Изначально, до изобретения электронных мониторов, цвет печатали. Для этого используется модель CMYK (Cyan, Magenta, Yellow, blacK). Цвета этой модели — обычные краски, только определенных, достаточно точных оттенков. Когда мы смешиваем magenta и yellow, то получаем красный цвет. Когда смешиваем cyan и yellow, то получаем зеленый. Если мешать все краски, кроме черного, то получим черный цвет (модель CMY). Черная краска же добавлялась по технологическим причинам: текст можно было печатать одной краской (а это экономия) и к тому же текст при этом не расплывался из-за ошибок смещения листа в печатном станке.
Поскольку CMYK и другие подобные модели ограничены физическими характеристиками красок, то они не могли охватить весь диапазон цветов. Например невозможно напечатать очень яркий красный цвет, потому что максимальная яркость будет ограничена малиновой краской.
Модель излучения sRGB
Когда появились первые цветные телевизоры, потом мониторы, то их цветовой охват был уже выше, чем CMYK, потому что электронно-лучевые трубки могли уже не отражать, а излучать цвет. Тогда кодировать цвет решили в модели RGB (red, green, blue), что довольно близко к устройству нашего глаза. На самом же деле RGB — это только базовая модель, которая охватывает очень много цветов, достаточных для подавляющего большинства задач.
С появлением компьютеров стала возможность генерировать цвет с помощью значений RGB и в 1996 году был утверждён стандарт sRGB (стандартный RGB), который на тот момент превосходил возможности мониторов.
В sRGB цвет задаётся в виде трёх значений отдельно для красного, зеленого и синего. Каждое значение может иметь значение от 0 до 255 (8 бит), что говорит о том, что у нас есть 256 градаций для каждого излучающего светодиода (раньше люминофор). Таким образом, мы можем посчитать, что всего может быть 16 777 216 отдельных цветов. Это очень много и до последнего времени даже не было мониторов, способных воспроизводить цвета за пределами sRGB.
Но технологии не стоят на месте и где-то после 2010 года стали появляться устройства, которые могут воспроизводить не 256 градаций на один цвет, а, скажем, 1000. Получается, что возможности устройств стали превышать возможности задавать цвета через sRGB.
Первыми такими устройствами были проекторы для кинозалов, которые могли создавать очень яркий свет. Если перед таким источником (ксеноновые лампы) условно поставить цветной светофильтр, то мы можем увидеть очень яркий цвет.
Чтобы понять о чём речь, вспомните например цвет сварки, или ярких неоновых огней, или даже цвет Солнца. Яркость этих объектов очень высока, но при этом мы всё равно может увидеть их цвет, потому что наш глаз обладает очень высоким динамическим диапазоном. Но из-за ограничения sRGB у нас нет возможности его математически описать.
В качестве развития модели RGB, был придуман Adobe RGB (1998), который похож на sRGB, только цвет задаётся в диапазоне от 0 до 1. Таким образом в Adobe RGB можно закодировать намного больше цветов, потому что используются дробные значения (это зависит от разрядности, например один канал может быть 16-битным). Если наложить Adobe RGB на CIE XYZ, то охват цветов будет примерно на 30% больше, чем в sRGB.
Сравнение цветовых моделей
Понятно, что по мере потребностей, придумывались разные цветовые модели, с той целью, чтобы охватить как можно больше диапазона CIE XYZ, но при этом не выйти за него. Общий смысл этих моделей в том, что нужно определить три базовых точки (цвета), которые будут соединены между собой — получится некий треугольник, который должен быть вписан в площадь CIE XYZ. Схематически это выглядит так:
Здесь, наверное, нужно отметить, что на таких диаграммах цвет не следует воспринимать буквально. Например зеленый цвет на этом графике — это на самом деле оттенки зеленого и чем он «выше», тем ярче будет этот цвет.
Самый «продвинутый» стандарт на сегодня — это Rec.2010 и Rec.2020 — это цветовой диапазон, который используется в проекторах, которые называются HDR-видео (не нужно путать с технологией создания фото). Нужно понимать, что цвета за пределами sRGB — это «экстремальные» цвета, они и в природе-то не так часто встречаются. Например блики хоть и яркие, но имеют какой-то цвет. В sRGB, да и в других ограниченных системах блики как правило просто белые, но в Rec.2020 можно указать ещё и какой-то цвет. Это же относится и к цвету в тенях. В sRGB в тёмных цветах насыщенность теряется, не говоря уже о том, что sRGB имеет очень малый динамический диапазон для темных тонов (любой фотограф понимает о чем речь, когда нужно снять темные и светлые участки одновременно).
То есть недостаточно просто придумать цветовую модель, нужно ещё и устройство, которое сможет воспроизвести этот цвет в физическом мире.
Судя по всему — сейчас впереди всех — это проекторы. Их устройство таково, что они могут создавать очень яркий свет и тем самым охватывать много цветов.
Что же касается DCI-P3, то сейчас это мониторы Apple, некоторые телевизоры и новые Android-смартфоны. То есть пока рано говорить о том, что устройства DCI-P3 играют существенную роль на рынке. Но, вполне возможно, что именно DCI-P3 будет следующим стандартом после sRGB, как только доля их устройств достигнет критической отметки. (Да, придётся покупать новые мониторы и ноуты.)
Совместимость
Сложность в том, что DCI-P3 совсем плохо сочетается с sRGB. Если например взять Adobe RGB, то используется очень близкие опорные точки, а значит цвет sRGB будет более-менее хорошо ложиться на Adobe RGB. Но вот DCI-P3 имеет другие опорные точки, что приводит к смещению цветов. Например если сделать макет в DCI-P3, а потом смотреть на мониторе sRGB, то мы увидим блеклые цвета, которые ещё и могут быть смещены по цветовому кругу.
Модели указания цвета
Поскольку мы работаем в sRGB, то цвет можно задать в виде трёх чисел. Это привычно, но неудобно, потому что тяжело по числам понять какой в реальности это цвет. Поэтому на помощь приходит модель HSL (HSV/HSB), где Hue — это оттенок на цветовом круге от 0 до 360 градусов; Saturation — насыщенность от 0% (серый) до 100% (полный цвет); Lightness — яркость/светлость от 0% до 100%. Когда яркость 100% — это белый цвет.
Модель HSL — это математические манипуляции с sRGB, поэтому формально мы не можем с помощью HSL задать больше цветов, чем в sRGB. Но поскольку мы все равно работаем с устройствами sRGB, то HSL очень удобная модель цвета. Не зря все дизайнеры и верстальщики работают только в ней.
Но, чтобы выйти за пределы sRGB придётся использовать другую модель.
OKLAB/OKLCH
Наиболее полной можно считать CIE Lab, где цвета задаются в виде яркости, оттенком между красным-зелёным и оттенком между синим-жёлтым. Вообразить себе это очень сложно, но из-за того, что это «идеальная» математическая модель, она используется повсеместно, например в Фотошопе, а также для того чтобы преобразовать цвет из одной модели в другую.
Но задавать цвет в Lab очень сложно, поэтому в web он практически не используется.
Частично эту проблему может решить новый Oklab (OKLCH), который задаётся как яркость (lightness) от 0% до 100%, хроматическая «насыщенность» (chroma) от 0 до примерно 0.4 и оттенок (hue) от 0 до 360 градусов.
В CSS для задания цвета используется функция oklch()
:
background: oklch(70% 0.1 16);
Для того, чтобы «поиграться», можно воспользоваться сайтом oklch.com. Выберите в качестве второго поля модель HSL. Для любопытных будет интересна статья «OKLCH in CSS: why we moved from RGB and HSL», где есть описания модели и множество примеров. И хотя авторы изрядно восхищаются OKLCH, всё-таки есть несколько подводных камней, которые не позволяют прямо сейчас перейти на эту цветовую модель.
Самое главное — это то, что сейчас мало устройств поддерживающих это цветовое пространство. Даже если вы сделаете переход на Oklab, то всё равно будете ограничены мониторами sRGB (своим или пользователей). Чтобы увидеть цвет потребуется именно сменить монитор.
Другая проблема — это сильная нелинейность OKLCH. При всех своих недостатках, HSL позволяет получить линейную градацию одного цветового оттенка путём смены одного параметра. В OKLCH же меняются сразу всё, иначе исходный оттенок получает смещение.
Вот так это выглядит на практике:
Упрощенный html-код:
<div style="background: oklch(90% 0.2 0)"></div> <div style="background: oklch(80% 0.2 0)"></div> <div style="background: oklch(70% 0.2 0)"></div> <div style="background: oklch(60% 0.2 0)"></div> <div style="background: oklch(50% 0.2 0)"></div> <div style="background: oklch(40% 0.2 0)"></div> <div style="background: oklch(30% 0.2 0)"></div> <div style="background: oklch(20% 0.2 0)"></div> <div style="background: oklch(10% 0.2 0)"></div>
В коде мы меняем только значение яркости от 10% до 90%, но при этом меняется и оттенок, хотя по идее он должен быть один и тот же. Если снять значение пипеткой, то оттенок гуляет от 323 до 357 градусов, причём это видно визуально.
Также заметьте, что цветовой тон мы задаём как 0°, что всегда соответствовало красному цвету, но в OKLCH это уже малиновый оттенок. Таким образом, если мы хотели бы использовать привычный цветовой круг HSL, то он не соответствует OKLCH — смещение примерно 30 градусов.
По сравнению с OKLCH, HSL ведёт себя более предсказуемо. Здесь оттенок 328° и насыщенность 70%, которые не меняются от яркости:
Еше пример нелинейности OKLCH. Теоретически это голубой/синий цвет, но при высокой яркости он срывается на какой-то неоновый оттенок.
Такие примеры показывают, что мы не можем использовать цвета oklch()
для получения правильных градаций одного оттенка цвета.
Чтобы получить подобную градацию в oklch()
придётся подбирать каждый цвет отдельно.
Код для тестирования в Berry CSS Builder:
<div class="b-flex"> <div class="pad30 mar3-r" style="background: hsl(208, 80%, 90%)"></div> <div class="pad30 mar3-r" style="background: hsl(208, 80%, 80%)"></div> <div class="pad30 mar3-r" style="background: hsl(208, 80%, 70%)"></div> <div class="pad30 mar3-r" style="background: hsl(208, 80%, 60%)"></div> <div class="pad30 mar3-r" style="background: hsl(208, 80%, 50%)"></div> <div class="pad30 mar3-r" style="background: hsl(208, 80%, 40%)"></div> <div class="pad30 mar3-r" style="background: hsl(208, 80%, 30%)"></div> <div class="pad30 mar3-r" style="background: hsl(208, 80%, 20%)"></div> <div class="pad30 mar3-r" style="background: hsl(208, 80%, 10%)"></div> </div> <div class="b-flex"> <div class="pad30 mar3-r" style="background: oklch(91.73% 0.0349 244.56)" title="90%"></div> <div class="pad30 mar3-r" style="background: oklch(83.58% 0.0706 245.19)" title="80%"></div> <div class="pad30 mar3-r" style="background: oklch(75.66% 0.1064 246.19)" title="70%"></div> <div class="pad30 mar3-r" style="background: oklch(68.17% 0.1404 247.96)" title="60%"></div> <div class="pad30 mar3-r" style="background: oklch(61.36% 0.17 251.26)" title="50%"></div> <div class="pad30 mar3-r" style="background: oklch(52.21% 0.1422 250.99)" title="40%"></div> <div class="pad30 mar3-r" style="background: oklch(42.65% 0.113 250.57)" title="30%"></div> <div class="pad30 mar3-r" style="background: oklch(32.52% 0.0816 249.84)" title="20%"></div> <div class="pad30 mar3-r" style="background: oklch(21.53% 0.0469 247.59)" title="10%"></div> </div>
Подобную нелинейность OKLCH показывает не только для получения яркостей одного оттенка, но и для получения оттенков одной яркости. Например мы можем задать цвет oklch(66% 0.1 208)
, но не можем задать oklch(66% 0.17 208)
, потому что значение 0.17 уже недопустимо для этого оттенка. Но при этом, если задать другой оттенок, то он уже отображается: oklch(66% 0.17 20)
.
Собственно эти примеры показывают, что ориентироваться в числах oklch()
достаточно сложно. И не удивительно, ведь это всё тот же Lab! Это же самое замечание касается и lch()
, которая оперирует уже процентами, но при этом не меняется суть. То есть в этим моделях мы можем задавать цвета, которые могут выходить за пределы реального отображения.
В заключении хотелось бы отметить, что Web — это не тоже самое, что и кино. При просмотре видео хочется более насыщенной и «настоящей» картинки и использование расширенного цветового пространства, видится вполне себе разумным развитием технологий. Но, поскольку это всё-таки «экстремальные» цвета, то в web-дизайне они скорее всего не будут востребованы, потому что никто в здравом уме не будет делать кнопку яркостью, сравнимой со сваркой. Поэтому на мой взгляд sRGB хватит на ближайшее десятилетие.
Слава Украине! Смерть рашистам!