OKLCH в CSS: изучаем цветовую модель на практических примерах
Если углубиться в изучение современного CSS, то может голова пойти кругом от обилия цветовых моделей и их особенностей. Зачем появилась еще одна, если многие веб-разработчики по-прежнему используют HEX-коды для работы с цветом? Попробуем выяснить, какие возможности открывает цветовая модель OKLCH.
OKLCH — это относительно новая цветовая модель, учитывающая особенности человеческого зрения, с помощью которой можно предсказуемо управлять цветом, меняя три параметра:
- L (Lightness / Яркость)
- C (Chroma / Насыщенность)
- H (Hue / Оттенок)
Пример:
oklch(0.6 0.2 270)
Можно также задать прозрачность:
oklch(0.6 0.2 270 / 0.5)
Цветовая модель OKLCH поддерживает работу с расширенными цветовыми пространствами: Display P3 и Rec. 2020. Стоит помнить, что математика OKLCH абстрагирована от физических ограничений существующего железа и позволяет накрутить параметры так, что цвет выйдет за рамки возможностей экрана. В этом случае современные браузеры приглушат сверх-насыщенные цвета, но для получения предсказуемого результата все значения следует проверять с помощью интерактивных инструментов.
Какие преимущества, кроме поддержки расширенных цветовых пространств, имеет OKLCH по сравнению с RGB? Допустим, на сайт нужно добавить несколько разноцветных элементов, имеющих одинаковую яркость. Если задавать цвета с помощью HEX-кодов, то для их подбора придется воспользоваться каким-либо графическим редактором или специализированным инструментом. В OKLCH достаточно изменить значение оттенка и оставить неизменными значения яркости и насыщенности:
oklch(0.5 0.16 20)
oklch(0.5 0.16 140)
oklch(0.5 0.16 260)
Теперь сравним OKLCH с цветовой моделью HSL, в которой цвет тоже задается тремя параметрами. Попробуем подобрать три цвета:
hsl(240, 100%, 50%)
hsl(120, 100%, 50%)
hsl(60, 100%, 50%)
Видим, что один из получившихся цветов, желтый, заметно светлее, и надпись на прямоугольнике потеряла читаемость. А ведь параметр светлоты был задан одинаковым для всех цветов.
А в чем отличие от модели LCH, у которой были те же самые параметры для работы с цветом и поддержка расширенных цветовых пространств? Попробуем постепенно увеличить яркость синего цвета с помощью обеих моделей:
lch(16.32 59.76 293.61)
lch(26.32 59.76 293.61)
lch(36.32 59.76 293.61)
lch(46.32 59.76 293.61)
lch(56.32 59.76 293.61)
oklch(0.3 0.155 265)
oklch(0.4 0.155 265)
oklch(0.5 0.155 265)
oklch(0.6 0.155 265)
oklch(0.7 0.155 265)
У LCH наглядно проявился ее главный математический баг, из-за которого у наиболее светлых квадратиков появился фиолетовый оттенок. А у модели OKLCH такого бага нет.
Об OKLCH можно рассказывать еще долго, но я предлагаю перейти к практике.
Подбор цветов
Раньше, если дизайнеру было необходимо подобрать цвет чуть темнее или светлее исходного, приходилось делать это на глаз. С появлением OKLCH эта рутина ушла в прошлое. Уже появились плагины для Figma, умеющие работать с OKLCH, но цвета можно подбирать и с помощью CSS. Допустим, нужно добавить на сайт три разноцветные колонки с кнопками. Цвет каждой кнопки должен быть производным от цвета фона своей секции, но темнее. Цвета кнопок при наведении курсора мыши должны становиться слегка светлее. В приведенном ниже коде добавлены значения оттенков и общее для всех цветов значение насыщенности в переменные CSS, а в стилях элементов прописаны значения для яркости.
HTML:
<div class="section">
<div class="section__column section__column_color_1">
<button class="button button_color_1">Кнопка 1</button>
</div>
<div class="section__column section__column_color_2">
<button class="button button_color_2">Кнопка 2</button>
</div>
<div class="section__column section__column_color_3">
<button class="button button_color_3">Кнопка 3</button>
</div>
</div>
CSS:
:root {
--color-hue1: 310;
--color-hue2: 350;
--color-hue3: 20;
--color-chroma: 0.11;
}
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: border-box;
}
.section {
display: flex;
}
.section__column {
flex: 0 0 auto;
width: 33.33333333%;
padding: 20px;
}
.section__column_color_1 {
background-color: oklch(0.8 var(--color-chroma) var(--color-hue1));
}
.section__column_color_2 {
background-color: oklch(0.8 var(--color-chroma) var(--color-hue2));
}
.section__column_color_3 {
background-color: oklch(0.8 var(--color-chroma) var(--color-hue3));
}
.button {
cursor: pointer;
width: 100%;
height: 100%;
background-color: var(--button-color);
border: none;
border-radius: 20px;
text-decoration: none;
padding: 20px;
color: oklch(1 0 0);
font-size: 24px;
font-weight: bold;
}
.button_color_1 {
--button-color: oklch(0.35 var(--color-chroma) var(--color-hue1));
}
.button_color_2 {
--button-color: oklch(0.35 var(--color-chroma) var(--color-hue2));
}
.button_color_3 {
--button-color: oklch(0.35 var(--color-chroma) var(--color-hue3));
}
.button:hover {
background-color: oklch(from var(--button-color) 0.45 c h);
}
Теперь, если будет нужно немного подкорректировать палитру, то после изменения значений переменных сразу изменятся цвета и у колонок и у кнопок. Правда удобно?
Автоматический контраст текста
Поскольку параметр яркости в OKLCH ведет себя предсказуемо, можно автоматически переключать цвет текста кнопки в зависимости от яркости ее фона. Сделать это можно средствами CSS, используя математические функции.
HTML:
<div class="section">
<div class="section__column">
<button class="button button_color_1">Белый текст</button>
</div>
<div class="section__column">
<button class="button button_color_2">Черный текст</button>
</div>
</div>
CSS:
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: border-box;
}
.section {
display: flex;
padding: 20px;
gap: 20px;
background-color: oklch(0.8975 0 0);
}
.section__column {
flex: 0 0 calc(50% - 10px);
}
.button {
--button-chroma: 0.12;
background-color: oklch(var(--button-lightness) var(--button-chroma) var(--button-hue));
--safe-lightness: clamp(0, var(--button-lightness), 1);
--text-lightness: calc(1 - round(var(--safe-lightness) - 0.1));
color: oklch(var(--text-lightness) 0 0);
cursor: pointer;
width: 100%;
height: 100%;
border: none;
border-radius: 20px;
text-decoration: none;
padding: 20px;
font-size: 24px;
font-weight: bold;
}
.button_color_1 {
--button-hue: 140;
--button-lightness: 0.4;
}
.button_color_2 {
--button-hue: 110;
--button-lightness: 0.8;
}
Видим, что у кнопки с темным фоном текст стал белым, а у другой, со светлым фоном, — черным. Стоит отметить, что в современных браузерах уже появилась поддержка функции contrast-color(), которая автоматически меняет цвет текста в зависимости от яркости фона. Но я решил показать, что эту задачу можно решить и по-другому.
Создание темной темы
Веб-разработчикам, которые используют HEX-коды, при создании темной темы приходится вручную переопределять цвета для элементов интерфейса. С помощью OKLCH эту задачу можно решить математически. В приведенном ниже коде внутри медиазапроса, срабатывающего при включении темной темы в настройках браузера или операционной системы, устанавливается значения для переменной --dark-theme равное единице. Это значение используется как математический множитель: если темная тема включена, то яркость элементов пересчитывается с помощью функции calc().
HTML:
<div class="gallery">
<div class="gallery-item">
<img class="gallery-item__image" src="image1.jpg" alt="">
<div class="gallery-item__text">Камышница</div>
</div>
<div class="gallery-item">
<img class="gallery-item__image" src="image2.jpg" alt="">
<div class="gallery-item__text">Кряква</div>
</div>
<div class="gallery-item">
<img class="gallery-item__image" src="image3.jpg" alt="">
<div class="gallery-item__text">Серая цапля</div>
</div>
</div>
CSS:
:root {
--dark-theme: 0;
--background-lightness: calc(0.89 - 0.71 * var(--dark-theme));
--item-background-lightness: calc(0.95 - 0.71 * var(--dark-theme));
--item-text-lightness: calc(0.19 + 0.69 * var(--dark-theme));
}
@media (prefers-color-scheme: dark) {
:root {
--dark-theme: 1;
}
}
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: border-box;
}
.gallery {
display: flex;
gap: 10px;
padding: 20px;
background-color: oklch(var(--background-lightness) 0 0);
}
.gallery-item {
flex: 0 0 calc(33.333% - 6.67px);
padding: 10px;
background-color: oklch(var(--item-background-lightness) 0 0);
}
.gallery-item__image {
display: block;
width: 100%;
}
.gallery-item__text {
font-size: 24px;
line-height: 1.0;
font-weight: bold;
text-align: center;
padding-top: 5px;
color: oklch(var(--item-text-lightness) 0 0);
}
Стоит ли начать использовать OKLCH?
На мой взгляд, OKLCH — это решение, избавляющее от многих проблем при работе с цветом. Как минимум, с этой цветовой моделью стоит познакомиться.





0 комментариев
Добавить комментарий