CSS: Что такое color-mix() и как смешивать цвета

Источник: «CSS color-mix()»
CSS функция color-mix() появилась в Chrome 111. В этой статье объясняется, как использовать эту функцию для смешивания цветов в таблицах стилей.

Смешивайте цвета в любом из поддерживаемых цветовых пространств прямо из вашего CSS.

До появления CSS функции color-mix() для затемнения, осветления или обесцвечивания цвета разработчики использовали препроцессоры CSS или функцию calc() для цветовых каналов.

Раньше с SCSS:

.color-mixing-with-sass {
/* Sass: поровну смешать красный и белый */
--red-white-mix: color.mix(red, white);
}

Sass проделал большую работу, опережая спецификацию цветов CSS. Однако реального способа смешивания цветов в CSS не существовало. Чтобы приблизиться, вам нужно выполнить расчёты частичных значений цвета. Вот уменьшенный пример того, как CSS может имитировать смешивание сегодня:

Раньше с HSL

.color-mixing-with-vanilla-css-before {
--lightness: 50%;
--red: hsl(0 50% var(--lightness));

/* добавить "белый" к красному
добавив 25% яркости к каналу
*/

--lightred: hsl(0 50% calc(var(--lightness) + 25%);
}

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

После:

.color-mixing-after {
/* поровну смешать красный с белым */
--red-white-mix: color-mix(in oklab, red, white);

/* поровну смешать красный с белым в srgb */
--red-white-mix-srgb: color-mix(in srgb, red, white);
}

Это то, что нам нужно. Гибкость, мощность и полнофункциональный API.

Смешивание цветов в CSS в color-mix()

CSS существует в множестве цветовых пространств и цветовых гамм, поэтому указывать цветовое пространство для смешивания необязательно. Кроме того, разные цветовые пространства могут резко изменить результаты смешивания, поэтому знание эффектов цветового пространства поможет вам получить нужные результаты.

Для ознакомления попробуйте этот интерактивный инструмент color-mix():

See the Pen

Смешивание в различных цветовых пространствах в color-mix()

Цветовое пространство по умолчанию для смешивания (и градиентов) — oklab. Оно обеспечивает стабильные результаты. Вы можете указать альтернативные цветовые пространства, чтобы адаптировать смешивание к вашим потребностям.

Возьмём, к примеру, black и white. Цветовое пространство, в котором они смешиваются, не будет иметь большого значения, верно? Неправильно.

color-mix(in srgb, black, white);
color-mix(in srgb-linear, black, white);
color-mix(in lch, black, white);
color-mix(in oklch, black, white);
color-mix(in lab, black, white);
color-mix(in oklab, black, white);
color-mix(in xyz, black, white);

See the Pen

Оно оказывает большой эффект!

Возьмём blue и white для другого примера. Я выбрал их специально, потому что это случай, когда форма цветового пространства может повлиять на результаты. В этом случае большинство цветовых пространств становятся фиолетовыми при переходе от белого к синему. Это также показывает, насколько oklab является надёжным цветовым пространством для смешивания, что оно наиболее близко к ожиданиям большинства людей в отношении смешивания белого и синего (без фиолетового)

color-mix(in srgb, blue, white);
color-mix(in srgb-linear, blue, white);
color-mix(in lch, blue, white);
color-mix(in oklch, blue, white);
color-mix(in lab, blue, white);
color-mix(in oklab, blue, white);
color-mix(in xyz, blue, white);

See the Pen

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

.black-to-white-gradient-in-each-space {
--srgb: linear-gradient(to right in srgb, black, white);
--srgb-linear: linear-gradient(to right in srgb-linear, black, white);
--lab: linear-gradient(to right in lab, black, white);
--oklab: linear-gradient(to right in oklab, black, white);
--lch: linear-gradient(to right in lch, black, white);
--oklch: linear-gradient(to right in oklch, black, white);
--hsl: linear-gradient(to right in hsl, black, white);
--hwb: linear-gradient(to right in hwb, black, white);
--xyz: linear-gradient(to right in xyz, black, white);
--xyz-d50: linear-gradient(to right in xyz-d50, black, white);
--xzy-d65: linear-gradient(to right in xyz-d65, black, white);
}

See the Pen

Если вам интересно, какое цветовое пространство является лучшим, то его нет. А вот почему так много вариантов! Также не было бы изобретено новых цветовых пространств (см. oklch и oklab), если бы одно из них было лучшим. Каждое цветовое пространство может иметь уникальный момент, чтобы сиять и быть правильным выбором.

Например, если вам нужен яркий результат смешивания, используйте hsl или hwb. В следующей демонстрации два ярких цвета (magenta и lime) смешиваются вместе, и hsl и hwb дают яркий результат, а srgb и oklab дают ненасыщенные цвета.

See the Pen

Если вам важно последовательность и тонкость, используйте oklab. В следующей демонстрации, которая смешивает синий и чёрный, hsl и hwb дают чрезмерно яркие цвета со смещёнными оттенками, а srgb и oklab дают более тёмно-синий.

See the Pen

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

Настройка метода интерполяции оттенка

Если вы выбрали смешивание для цилиндрического цветового пространства, т.е. любое цветовое пространство с каналом оттенка h, принимающим угол. Вы можете указать будет ли интерполяция короче shorter, длиннее longer, уменьшаться decreasing или увеличиваться increasing. Если вы хотите узнать больше, это хорошо описано в HD Color Guide.

Игровая площадка color-mix() добавляет дополнительный раскрывающийся список выбора, если цветовое пространство цилиндрическое. Вы можете поиграться в нём, чтобы увидеть эффекты смешивания.

Вот тот же пример сочетания синего и белого, но на этот раз только в цилиндрических пространствах с разными методами интерполяции оттенков.

See the Pen

Вот ещё один Codepen, который я сделал, чтобы помочь визуализировать интерполяцию оттенков, но специально для градиентов. Я полагаю, что это поможет вам понять, как каждое цветовое пространство даёт свой результат микширования, когда указана интерполяция оттенков, изучите его!

See the Pen

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

Смешивание цветов в color-mix() с различными цветовыми синтаксисами

До сих пор мы в основном смешивали именованные цвета CSS, например blue и white. Смешивание CSS цветов позволяет смешивать цвета из двух разных цветовых пространств. Это ещё одна причина, по которой важно указывать цветовое пространство для смешивания, поскольку оно устанавливает общее пространство, когда цвета не находятся в одном цветовом пространстве.

color-mix(in oklch, hsl(200deg 50% 50%), color(display-p3 .5 0 .5));

В этом примере hsl и display-p3 будут преобразованы в oklch, а затем смешаны. Довольно круто и гибко.

Регулирование пропорций смешивания цветов в color-mix()

Маловероятно, что каждый раз, когда вы смешиваете, вам нужны равные части каждого цвета, как показано в большинстве примеров. Хорошие новости, есть синтаксис для определения того, сколько каждого цвета должно быть видно в результирующем миксе.

Чтобы начать эту тему, вот пример миксов, которые все эквивалентны (и из спецификации):

.ratios-syntax-examples {
/* опустить процент для равных пропорций */
color: color-mix(in lch, purple, plum);
color: color-mix(in lch, plum, purple);

/* процент может указываться по обе стороны от цвета */
color: color-mix(in lch, purple 50%, plum 50%);
color: color-mix(in lch, 50% purple, 50% plum);

/* процент только для одного цвета? другой получает остаток */
color: color-mix(in lch, purple 50%, plum);
color: color-mix(in lch, purple, plum 50%);

/* проценты > 100% пропорционально сжимаются */
color: color-mix(in lch, purple 80%, plum 80%);
/* вышеприведённый мик сжимается до этого */
color: color-mix(in lch, purple 50%, plum 50%);
}

Я считаю, что эти примеры хорошо освещают крайние случаи. Первый набор показывает, что 50% необязательны, но могут быть указаны дополнительно. Последний пример показывает интересный случай, когда соотношение превышают 100% при суммировании, они пропорционально ограничиваются до 100%.

Заметьте также, что если только один цвет определяет соотношение, другой считается остатком до 100%. Вот ещё несколько примеров иллюстрирующих такое поведение.

color-mix(in lch, purple 40%, plum) /* plum присваивается 60% */
color-mix(in lch, purple, 60% plum) /* purple присваивается 40% */
color-mix(in lch, purple 40%, plum 60%) /* нет автоматического присваивания */

Эти примеры иллюстрируют два правила:

  1. Когда соотношения превышает 100%, они сжимаются и распределяются поровну.
  2. Если задано только одно соотношение, для другого цвета устанавливается значение 100% минус это соотношение.

Последнее правило немного менее очевидно. Что произойдёт, если проценту казаны для обоих цветов, но в сумме они не составляют 100%?

color-mix(in lch, purple 20%, plum 20%)

Эта комбинация color-mix() приводит к прозрачности, 40% прозрачности. Когда соотношение не составляет 100%, полученная смесь будет прозрачной. Ни один из цветов не будет полностью смешан.

Вложение color-mix()

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

color-mix(in lch, purple 40%, color-mix(plum, white))

Не стесняйтесь вкладывать столько, сколько вам нужно, чтобы получить результат к которому вы стремитесь.

Создание светлой и тёмной цветовой схемы с color-mix()

Давайте создадим цветовые схемы с color-mix()!

Основная цветовая схема с color-mix()

В следующем примере светлая и тёмная темы создаются на основе шестнадцатеричного значения цвета brand. Светлая тема создаёт два тёмно-синих цвета текста и очень светлый белый цвет поверхности фона. Затем @media (prefers-color-scheme: dark) настраиваемым свойствам назначаются новые цвета, поэтому фон становится тёмным, а цвет текста светлым.

:root {
/* базовый цвет brand */
--brand: #0af;

/* очень тёмный brand синий */
--text1: color-mix(in oklab, var(--brand) 25%, black);
--text2: color-mix(in oklab, var(--brand) 40%, black);

/* очень светлый brand белый */
--surface1: color-mix(in oklab, var(--brand) 5%, white);
}

@media (prefers-color-scheme: dark) {
:root {
--text1: color-mix(in oklab, var(--brand) 15%, white);
--text2: color-mix(in oklab, var(--brand) 40%, white);
--surface1: color-mix(in oklab, var(--brand) 5%, black);
}
}

Всё это достигается путём смешивания белого или чёрного цвета со значением цвета brand.

See the Pen

Промежуточная цветовая схема с color-mix()

Можно пойти ещё дальше, добавив больше светлых и тёмных тем. В следующей демонстрации изменения в группе переключателей обновляют атрибут HTML-тэга [color-scheme="auto"], который позволяет селекторам условно менять цветовую тему.

See the Pen

Эта демонстрация промежуточной цветовой схемы также демонстрирует технику цветовой тематики, в которой все цвета темы перечислены в :root. Это позволяет легко увидеть их все вместе и при необходимости отрегулировать. Позже в таблице стилей вы можете использовать переменные по мере их определения. Это избавляет от поиска в таблице стилей цветовых манипуляций, поскольку все они содержатся в начальном блоке :root.

Более интересные примеры использования color-mix()

У Ana Tudor есть отличная демонстрация с несколькими вариантами использования color-mix() для изучения:

See the Pen

Отладка color-mix() с помощью DevTools

Chrome DevTools отлично поддерживает функцию color-mix(). Он распознаёт и выделяет синтаксис, создаёт предварительный просмотр смешивания цветов прямо рядом со стилем на панели Стили/Styles и позволяет выбирать альтернативные цвета.

В DevTools это выглядит пример так:

color-mix() в Chrome DevTools

Всем удачного микширования/смешивания!

Дополнительные материалы

Предыдущая Статья

Laravel: Всё, что вы можете протестировать в приложении

Следующая Статья

Laravel: Моделирование бизнес процессов