Color functions
Современные CSS-функции для работы с цветом:
color-mix,light-dark,oklch,oklab— дают точный контроль над палитрой, тематизацией и восприятием цвета.
Зачем нужно
Классические hex и rgb имеют ограничения: узкая цветовая гамма (sRGB), неперцептивная равномерность (одинаковое числовое изменение не даёт одинакового визуального изменения). Новые функции решают эти проблемы и упрощают создание тем и палитр.
Где используется
- Создание палитр из одного базового цвета
- Тёмная / светлая тема через
light-dark - Смешивание цветов без препроцессоров
- Широкая цветовая гамма (P3) для HDR-дисплеев
- Перцептивно равномерные градиенты (oklch)
Предпосылки
- CSS переменные — переменные для хранения цветов
oklch — перцептивное цветовое пространство
oklch(L C H) — Lightness (0-100%), Chroma (насыщенность), Hue (оттенок 0-360):
:root {
/* oklch(lightness chroma hue) */
--blue: oklch(60% 0.2 250);
--red: oklch(60% 0.2 25);
--green: oklch(60% 0.2 145);
--purple: oklch(60% 0.2 300);
/* Все имеют ОДИНАКОВУЮ воспринимаемую яркость!
В rgb это было бы невозможно */
}
.button-blue { background: var(--blue); }
.button-red { background: var(--red); }
.button-green { background: var(--green); }
.button-purple { background: var(--purple); }
Генерация палитры через lightness
:root {
--hue: 250; /* Базовый оттенок */
--chroma: 0.15;
--color-50: oklch(97% var(--chroma) var(--hue));
--color-100: oklch(93% var(--chroma) var(--hue));
--color-200: oklch(85% var(--chroma) var(--hue));
--color-300: oklch(75% var(--chroma) var(--hue));
--color-400: oklch(65% var(--chroma) var(--hue));
--color-500: oklch(55% var(--chroma) var(--hue));
--color-600: oklch(45% var(--chroma) var(--hue));
--color-700: oklch(35% var(--chroma) var(--hue));
--color-800: oklch(25% var(--chroma) var(--hue));
--color-900: oklch(15% var(--chroma) var(--hue));
}
oklch с прозрачностью
.overlay {
background: oklch(20% 0 0 / 0.5); /* 50% прозрачный тёмный */
}
oklab — перцептивное смешивание
oklab(L a b) — похож на oklch, но использует координаты a (зелёный-красный) и b (синий-жёлтый):
.element {
color: oklab(60% -0.1 0.1);
/* L: яркость, a: зелёный(-) / красный(+), b: синий(-) / жёлтый(+) */
}
oklchудобнее для людей (hue = угол на цветовом колесе).oklabлучше для вычислений и плавных переходов.
color-mix — смешивание цветов
.element {
/* Смешать 50% красного и 50% синего */
background: color-mix(in oklch, red, blue);
/* 70% первого + 30% второго */
background: color-mix(in oklch, #007bff 70%, white);
/* Осветление — смешать с белым */
--light: color-mix(in oklch, var(--color-primary) 80%, white);
/* Затемнение — смешать с чёрным */
--dark: color-mix(in oklch, var(--color-primary) 80%, black);
}
Палитра через color-mix
:root {
--brand: #007bff;
--brand-50: color-mix(in oklch, var(--brand) 5%, white);
--brand-100: color-mix(in oklch, var(--brand) 15%, white);
--brand-200: color-mix(in oklch, var(--brand) 30%, white);
--brand-300: color-mix(in oklch, var(--brand) 50%, white);
--brand-400: color-mix(in oklch, var(--brand) 70%, white);
--brand-500: var(--brand);
--brand-600: color-mix(in oklch, var(--brand) 85%, black);
--brand-700: color-mix(in oklch, var(--brand) 70%, black);
--brand-800: color-mix(in oklch, var(--brand) 50%, black);
--brand-900: color-mix(in oklch, var(--brand) 30%, black);
}
Цветовые пространства для смешивания
/* in srgb — классическое смешивание */
color-mix(in srgb, red, blue); /* Тусклый фиолетовый */
/* in oklch — перцептивно равномерное */
color-mix(in oklch, red, blue); /* Яркий фиолетовый */
/* in oklch longer hue — через длинную дугу цветового колеса */
color-mix(in oklch longer hue, red, blue); /* Через зелёный/жёлтый */
light-dark — автоматическая тема
:root {
color-scheme: light dark; /* Поддержка обеих тем */
}
body {
background: light-dark(#ffffff, #1a1a1a);
color: light-dark(#333333, #e0e0e0);
}
.card {
background: light-dark(#f8f9fa, #2d2d2d);
border: 1px solid light-dark(#dee2e6, #404040);
box-shadow: light-dark(
0 2px 8px rgba(0, 0, 0, 0.08),
0 2px 8px rgba(0, 0, 0, 0.3)
);
}
.button {
background: light-dark(#007bff, #4dabff);
color: light-dark(white, #1a1a1a);
}
/* Переключение через класс или @media */
:root {
color-scheme: light; /* По умолчанию светлая */
}
@media (prefers-color-scheme: dark) {
:root {
color-scheme: dark;
}
}
/* Или ручное переключение */
.theme-dark {
color-scheme: dark;
}
color — расширенная цветовая гамма
.vibrant {
/* Display P3 — шире sRGB, для современных дисплеев */
background: color(display-p3 1 0.2 0.1);
/* Fallback для старых браузеров */
background: #ff3311;
background: color(display-p3 1 0.2 0.1);
}
/* Проверка поддержки */
@supports (color: color(display-p3 0 0 0)) {
.vibrant {
background: color(display-p3 1 0.2 0.1);
}
}
Относительные цвета (Relative Color Syntax)
:root {
--brand: oklch(55% 0.2 250);
}
.button {
background: var(--brand);
}
.button:hover {
/* Взять --brand и изменить lightness на +10% */
background: oklch(from var(--brand) calc(l + 0.1) c h);
}
.button:active {
/* Затемнить */
background: oklch(from var(--brand) calc(l - 0.1) c h);
}
/* Создать полупрозрачную версию */
.badge {
background: oklch(from var(--brand) l c h / 0.2);
color: var(--brand);
}
Частые ошибки
- oklch chroma вне диапазона — браузер обрезает до ближайшего допустимого:
/* Слишком насыщенный — будет обрезан */ color: oklch(50% 0.5 150); /* 0.5 слишком много для зелёного */ light-darkбезcolor-scheme— функция требуетcolor-schemeна элементе или предкеcolor-mix(in srgb)даёт тусклые промежуточные — используйтеin oklchдля лучшего результата- Забыли fallback — Display P3 не поддерживается в старых браузерах
Практика
- Создать палитру из 10 оттенков через oklch (меняя lightness)
- Использовать
color-mixдля hover-состояний (осветление/затемнение) - Реализовать тёмную тему через
light-dark - Сравнить градиент в
srgbиoklch— увидеть разницу - Попробовать relative color syntax для hover-эффектов
Связанные темы
- CSS переменные — хранение цветов
- filter — визуальные эффекты с цветами
- mix-blend-mode — смешивание слоёв