Уроки

CSS color-mix(): нативное смешивание цветов в браузере

8 мин чтения

На протяжении лет генерация вариантов цвета в CSS требовала либо жёсткого задания каждого оттенка вручную, либо обращения к JavaScript и библиотеке работы с цветами вроде chroma.js или tinycolor2. Функция CSS color-mix() меняет это. Это нативная CSS-функция, теперь поддерживаемая всеми основными браузерами, которая смешивает два цвета в заданной пропорции — прямо в таблице стилей, без JavaScript и без препроцессинга.

Эта статья полностью охватывает синтаксис, объясняет, почему выбор цветового пространства меняет всё, рассматривает практические кейсы, делающие color-mix() действительно полезным, и касается поддержки браузеров и стратегий запасных вариантов.

Что такое color-mix()?

color-mix() — функция CSS Color Level 5, принимающая два значения цвета и пропорцию смешивания и возвращающая результирующий смешанный цвет. Это CSS-эквивалент смешивания двух красок, но с критическим дополнительным параметром: цветовым пространством, в котором происходит смешивание.

Простейший кейс — создание оттенков от базового цвета. Вместо определения каждого варианта оттенка фирменного синего вручную можно получать их динамически:

:root {
  --brand-blue: #2563EB;

  /* Осветления — смешиваем с белым */
  --brand-blue-light:   color-mix(in oklch, var(--brand-blue) 60%, white);
  --brand-blue-lighter: color-mix(in oklch, var(--brand-blue) 30%, white);

  /* Затемнения — смешиваем с чёрным */
  --brand-blue-dark:    color-mix(in oklch, var(--brand-blue) 80%, black);
  --brand-blue-darker:  color-mix(in oklch, var(--brand-blue) 50%, black);
}

Базовый синий #2563EB определяется один раз. Осветления и затемнения выводятся из него. При изменении фирменного цвета все варианты обновляются автоматически.

Синтаксис и параметры

Полный синтаксис color-mix():

color-mix(in <color-space>, <color1> [<percentage>]?, <color2> [<percentage>]?)

Параметр цветового пространства

Первый аргумент, in <color-space>, обязателен и задаёт место, где происходит смешивание. Допустимые варианты:

  • srgb — смешивание в стандартном RGB (наиболее знакомый, но склонный к тусклым средним точкам)
  • hsl — смешивание вдоль цилиндра HSL
  • hwb — смешивание в HWB (Оттенок, Белизна, Чернота)
  • lab — смешивание в CIE Lab (перцептуально равномерный)
  • oklab — смешивание в Oklab (лучшая равномерность, чем у CIE Lab)
  • lch — смешивание в LCH (цилиндрический CIE Lab)
  • oklch — смешивание в OKLCH (цилиндрический Oklab, рекомендуется для большинства задач)
  • display-p3 — смешивание в широкой гамме Display P3
  • xyz — смешивание в CIE XYZ

Для большинства дизайнерской работы oklch даёт наиболее перцептуально естественные результаты. Подробнее об этом — в следующем разделе.

Аргументы цвета

Два значения цвета могут быть любым допустимым CSS-цветом: HEX-коды, rgb(), hsl(), oklch(), именованные цвета или пользовательские свойства CSS. Каждый может опционально иметь процентное значение, указывающее, насколько этот цвет вносит вклад в смесь:

/* Смешивание 50/50 (по умолчанию, если проценты не указаны) */
color-mix(in oklch, #FF5733, #3498DB)

/* 70% первого цвета, 30% второго */
color-mix(in oklch, #FF5733 70%, #3498DB 30%)

/* 80% первого цвета — процент второго выводится как 20% */
color-mix(in oklch, #FF5733 80%, #3498DB)

Если проценты суммируются менее 100%, результат частично прозрачен. Если они превышают 100%, проценты нормализуются. Если ни один процент не указан, смешивание 50/50.

/* Они эквивалентны */
color-mix(in srgb, blue, red)
color-mix(in srgb, blue 50%, red 50%)
color-mix(in srgb, blue 50%, red)

Смешивание в разных цветовых пространствах

Выбор цветового пространства не косметический — он фундаментально меняет производимый цвет. Те же два цвета, смешанные в разных пространствах, дают кардинально разные результаты.

Смешивание в sRGB

Смешивание в sRGB работает путём линейной интерполяции каналов красного, зелёного и синего. Для многих пар цветов это даёт приемлемые результаты, но дополнительные цвета (находящиеся на противоположных сторонах цветового круга) часто дают десатурированную, сероватую среднюю точку.

/* Смешивание оранжево-красного и синего в sRGB */
color-mix(in srgb, #FF5733 50%, #3498DB 50%)
/* Результат: приглушённый, несколько коричневатый фиолетовый — диапазон [#9A77B7] */

Проблема в том, что RGB-каналы дополнительных цветов компенсируют друг друга при усреднении. Красный [255, 87, 51] и Синий [52, 152, 219] дают среднюю точку [154, 120, 135] — десатурированный, «замутнённый» результат.

Смешивание в HSL

Смешивание в HSL интерполирует вдоль цветового круга, что может вызвать другую проблему: вращение оттенка через неожиданные промежуточные цвета.

/* Оранжевый (оттенок ~15°) смешан с синим (оттенок ~210°) в HSL */
color-mix(in hsl, #FF5733 50%, #3498DB 50%)
/* Оттенок интерполируется через ~112° — получается зеленоватый промежуточный */

Когда два цвета далеко друг от друга на цветовом круге, кратчайший путь между ними в HSL может проходить через зелёный или другие неожиданные оттенки. HSL также разделяет проблему перцептуальной неравномерности hsl() в целом — средняя точка светлоты может не выглядеть как середина между двумя исходными светлотами.

Смешивание в OKLCH

Смешивание в OKLCH является рекомендуемым подходом для большинства практических задач. Оно интерполирует в перцептуально равномерном пространстве, что означает, что промежуточные цвета выглядят как естественные визуальные середины — яркие, сбалансированные, без неожиданного смещения оттенка.

/* Оранжево-красный смешан с синим в OKLCH */
color-mix(in oklch, #FF5733 50%, #3498DB 50%)
/* Результат: яркий пурпурно-сиреневый — перцептуально посередине */

#FF5733 (тёплый оранжево-красный) и #3498DB (яркий синий), смешанные 50/50 в OKLCH, дают насыщенный промежуточный. Оттенок интерполирует прямо через фиолетовый диапазон — именно то, чего ожидает дизайнер, когда его просят «найти среднее» между оранжевым и синим.

Смешивание в Oklab (кратчайший/длиннейший путь оттенка)

Для интерполяции оттенка можно также указать, следовать ли по более короткой или длинной дуге вокруг цветового круга:

/* Кратчайший путь оттенка (по умолчанию) */
color-mix(in oklch shorter hue, red, blue)

/* Длиннейший путь оттенка — идёт в другую сторону вокруг круга */
color-mix(in oklch longer hue, red, blue)

/* Возрастающий оттенок */
color-mix(in oklch increasing hue, red, blue)

Этот контроль полезен, когда намеренно нужна интерполяция, проходящая через определённые промежуточные оттенки — например, градиент, идущий от красного через жёлтый к синему, а не через фиолетовый.

Таблица сравнения

Цветовое пространство Середина оранжевый + синий Визуальный характер
srgb Приглушённый сероватый фиолетовый Десатурированный, мутный
hsl Зеленоватый Неожиданный сдвиг оттенка
lab Фиолетовый, менее яркий Естественнее, чем sRGB
oklch Яркий пурпурно-сиреневый Наиболее перцептуально естественный

Используйте конвертер цветов для изучения OKLCH-значений ваших конкретных цветов и предсказания того, как они будут смешиваться.

Практические кейсы

Создание состояний наведения и нажатия

Одно из наиболее немедленно полезных применений — генерация интерактивных состояний без определения отдельных переменных для каждого:

:root {
  --btn-bg: oklch(0.55 0.22 250);  /* Ваш фирменный синий */
}

.btn {
  background-color: var(--btn-bg);
}

.btn:hover {
  /* Затемнить на 15%, смешивая с чёрным */
  background-color: color-mix(in oklch, var(--btn-bg) 85%, black);
}

.btn:active {
  /* Затемнить больше для нажатого состояния */
  background-color: color-mix(in oklch, var(--btn-bg) 70%, black);
}

.btn:disabled {
  /* Десатурировать и осветлить для отключённого */
  background-color: color-mix(in oklch, var(--btn-bg) 40%, white);
  opacity: 0.6;
}

Это устраняет необходимость выбирать три отдельных оттенка в дизайн-инструменте и жёстко их задавать. Цвета наведения и нажатия математически выводятся из базового, сохраняя согласованность отношений даже при смене фирменного цвета.

Создание семантических цветовых шкал

Системы дизайна нуждаются в семантических цветах — успех, предупреждение, опасность — гармонирующих с фирменной палитрой. color-mix() позволяет получать их из фирменного цвета, а не выбирать независимо:

:root {
  --brand: oklch(0.55 0.22 250);  /* Фирменный синий */

  /* Успех: смешиваем бренд с чистым зелёным, сохраняя намёк на идентичность бренда */
  --success: color-mix(in oklch, oklch(0.65 0.22 145) 85%, var(--brand) 15%);

  /* Предупреждение: чистый янтарь — без смешивания */
  --warning: oklch(0.75 0.18 70);

  /* Опасность: чистый красный */
  --danger: oklch(0.62 0.24 25);

  /* Тонированные фоны для каждого состояния */
  --success-bg: color-mix(in oklch, var(--success) 12%, white);
  --warning-bg: color-mix(in oklch, var(--warning) 12%, white);
  --danger-bg:  color-mix(in oklch, var(--danger)  12%, white);
}

--success-bg — очень светлый оттенок зелёного успеха, выведенный автоматически. Используйте их для баннеров уведомлений, окон оповещений и состояний ошибок полей форм.

Динамическая генерация полных шкал оттенков

Хотя Генератор оттенков — правильный инструмент для создания полной шкалы 50–950 с точными перцептуальными шагами, color-mix() может генерировать пригодное приближение в строках кода для компонентов, нуждающихся в нескольких вариантах:

:root {
  --primary: oklch(0.58 0.20 250);

  --primary-50:  color-mix(in oklch, var(--primary) 8%,  white);
  --primary-100: color-mix(in oklch, var(--primary) 15%, white);
  --primary-200: color-mix(in oklch, var(--primary) 30%, white);
  --primary-300: color-mix(in oklch, var(--primary) 50%, white);
  --primary-400: color-mix(in oklch, var(--primary) 70%, white);
  --primary-500: var(--primary);
  --primary-600: color-mix(in oklch, var(--primary) 85%, black);
  --primary-700: color-mix(in oklch, var(--primary) 70%, black);
  --primary-800: color-mix(in oklch, var(--primary) 55%, black);
  --primary-900: color-mix(in oklch, var(--primary) 35%, black);
  --primary-950: color-mix(in oklch, var(--primary) 20%, black);
}

Получение цветов тёмного режима

color-mix() особенно ценен для систематического получения цветов поверхностей в тёмном режиме:

@media (prefers-color-scheme: dark) {
  :root {
    --surface-base:     #09090b;
    --surface-elevated: color-mix(in oklch, var(--brand) 8%, #09090b);
    --surface-overlay:  color-mix(in oklch, var(--brand) 12%, #09090b);
  }
}

Смешивание небольшого количества фирменного цвета в тёмные поверхности создаёт тонкий оттенок — техника, используемая macOS от Apple и многими современными системами дизайна, чтобы тёмный режим ощущался менее стерильным, чем чисто нейтральные поверхности.

Поведение альфа-канала

Когда проценты не суммируются до 100%, результат частично прозрачен. Это можно использовать намеренно для создания полупрозрачных вариантов:

/* 30% синего на прозрачной основе — эквивалент rgba при 30% прозрачности */
color-mix(in srgb, blue 30%, transparent)

/* Также допустимо: именованная прозрачность с другой стороны */
color-mix(in oklch, #3B82F6 25%, transparent)

Это заменяет паттерн использования rgba() с фиксированным альфа. Преимущество в том, что отношение прозрачности явно выражено в проценте смешивания, и можно смешивать с любым цветом — а не только с чистой прозрачностью.

Поддержка браузеров и запасные варианты

По состоянию на 2026 год color-mix() полностью поддерживается в:

  • Chrome/Edge: с версии 111 (март 2023)
  • Firefox: с версии 113 (май 2023)
  • Safari: с версии 16.2 (декабрь 2022)

Глобальная поддержка превышает 90%. Пользователи, не видящие результаты color-mix(), — это те, кто работает с очень старыми мобильными браузерами или в корпоративных средах с заблокированными версиями браузеров.

Запасной вариант с прогрессивным улучшением

Объявления пользовательских свойств CSS каскадируются. Если браузер не поддерживает color-mix(), используется запасной вариант из предыдущей строки:

:root {
  /* Запасной вариант для браузеров без color-mix() */
  --btn-hover: #1D4ED8;

  /* Переопределение с вычисленным значением для современных браузеров */
  --btn-hover: color-mix(in oklch, var(--btn-bg) 85%, black);
}

Поскольку пользовательские свойства повторно объявляют одну и ту же переменную, это работает как паттерн прогрессивного улучшения. Браузеры без поддержки color-mix() используют явный запасной цвет; современные браузеры используют выведенное значение.

Альтернативно используйте @supports:

.btn:hover {
  background-color: #1D4ED8; /* Запасной вариант */
}

@supports (color: color-mix(in oklch, red, blue)) {
  .btn:hover {
    background-color: color-mix(in oklch, var(--btn-bg) 85%, black);
  }
}

Подход @supports более явный и его проще убрать, когда вы в конечном счёте откажетесь от поддержки старых браузеров.

Ключевые выводы

  • color-mix() смешивает два цвета нативно в CSS, устраняя для многих кейсов необходимость в JavaScript или предварительно сгенерированных таблицах оттенков.
  • Аргумент in <color-space> управляет местом смешивания и кардинально влияет на результат. Используйте oklch для большинства работ — он даёт перцептуально естественные средние точки без мутной десатурации (проблема sRGB) и неожиданных смещений оттенка (проблема HSL).
  • Наиболее практичные кейсы: интерактивные состояния (наведение, нажатие, отключение), получение семантических цветов, тонирование поверхностей тёмного режима и генерация небольших шкал оттенков из одной базовой переменной.
  • Когда проценты суммируются менее 100%, результат частично прозрачен — полезно для создания вариантов прозрачности без rgba().
  • Поддержка браузеров охватывает все современные браузеры с начала 2023 года. Предоставьте жёстко заданный запасной вариант в предшествующем CSS-объявлении или внутри блока @supports для старых сред.
  • Используйте конвертер цветов для перевода существующих фирменных цветов в OKLCH перед использованием в color-mix(), а генератор палитр для просмотра гармоничных цветовых отношений перед написанием CSS.

Похожие цвета

Похожие бренды

Похожие инструменты