Современные цвета
В уроке о цветах были rgb() и hsl(). У них есть недостаток: числа плохо совпадают с тем, как цвет видит глаз. Современный CSS добавил функцию oklch(), в которой одинаковые числа означают одинаковую на вид яркость, и инструменты, чтобы получать новые цвета из уже существующих.
Функция oklch()
oklch() принимает три числа: светлоту L (от 0% — чёрный, до 100% — белый), насыщенность C (от 0 — серый, примерно до 0.37 — самый яркий) и оттенок H — угол на цветовом круге от 0 до 360:
<style>
.swatch { display: inline-block; width: 90px; padding: 24px 0; text-align: center; color: white; }
</style>
<div class="swatch" style="background: oklch(60% 0.2 25);">красный</div>
<div class="swatch" style="background: oklch(60% 0.2 145);">зелёный</div>
<div class="swatch" style="background: oklch(60% 0.2 260);">синий</div>Устройство похоже на hsl(), только порядок другой: сначала светлота, в конце оттенок.
Почему не hsl()
Светлота в hsl() — математическая, а не та, что видит глаз. При одинаковых 50% жёлтый выглядит почти белым, а синий — тёмным. В oklch() одинаковая светлота действительно выглядит одинаково:
<style>
.row { display: flex; gap: 4px; margin-bottom: 4px; }
.row div { flex: 1; padding: 12px 0; text-align: center; }
</style>
<div class="row">
<div style="background: hsl(60 100% 50%);">hsl</div>
<div style="background: hsl(120 100% 50%);">hsl</div>
<div style="background: hsl(240 100% 50%);">hsl</div>
</div>
<div class="row">
<div style="background: oklch(75% 0.15 100);">oklch</div>
<div style="background: oklch(75% 0.15 145);">oklch</div>
<div style="background: oklch(75% 0.15 260);">oklch</div>
</div>В верхнем ряду текст на синем почти не читается, в нижнем все три цвета одинаково светлые.
Палитра из одного оттенка
Раз светлота честная, палитру получают, меняя только первое число. Оттенок вынесен в переменную — поменяйте его, и вся шкала перекрасится:
<style>
.palette { --hue: 260; display: flex; }
.palette div { flex: 1; height: 40px; }
</style>
<div class="palette">
<div style="background: oklch(95% 0.03 var(--hue));"></div>
<div style="background: oklch(80% 0.1 var(--hue));"></div>
<div style="background: oklch(65% 0.15 var(--hue));"></div>
<div style="background: oklch(50% 0.15 var(--hue));"></div>
<div style="background: oklch(35% 0.1 var(--hue));"></div>
</div>Смешивание: color-mix()
color-mix() смешивает два цвета в заданной пропорции. Первым аргументом указывают, в каком пространстве смешивать, — обычно in oklch. Так получают оттенок для наведения из фирменного цвета:
<style>
:root { --brand: royalblue; }
.btn { padding: 8px 16px; border: none; color: white; background: var(--brand); }
.btn:hover { background: color-mix(in oklch, var(--brand), black 25%); }
.soft { padding: 8px; margin-top: 8px; background: color-mix(in oklch, var(--brand) 15%, white); }
</style>
<button class="btn">Наведите на кнопку</button>
<div class="soft">Бледный фон из того же цвета</div>Относительные цвета
Относительный синтаксис берёт готовый цвет, раскладывает его на части l, c и h и собирает новый. Каждую часть можно оставить или изменить через calc():
<style>
:root { --brand: oklch(55% 0.18 260); }
.box { display: inline-block; width: 100px; padding: 16px 0; text-align: center; color: white; }
</style>
<div class="box" style="background: var(--brand);">основной</div>
<div class="box" style="background: oklch(from var(--brand) calc(l + 0.2) c h);">светлее</div>
<div class="box" style="background: oklch(from var(--brand) l c calc(h + 180));">напротив</div>
<div class="box" style="background: oklch(from var(--brand) l c h / 40%);">прозрачный</div>Поменяйте --brand — все производные цвета пересчитаются. oklch() и color-mix() работают во всех основных браузерах с 2023 года, относительный синтаксис — с 2024 года.
Частая ошибка
Светлота без знака процента. В oklch() светлоту можно писать процентами или числом от 0 до 1. Запись oklch(70 0.15 250) означает не 70%, а 70 — больше единицы, и цвет становится белым:
<style>
div { padding: 12px; margin-bottom: 4px; border: 1px solid silver; }
</style>
<div style="background: oklch(70 0.15 250);">oklch(70 0.15 250) — белый</div>
<div style="background: oklch(70% 0.15 250);">oklch(70% 0.15 250) — голубой</div>
<div style="background: oklch(0.7 0.15 250);">oklch(0.7 0.15 250) — тоже голубой</div>