color()

Обеспечиваем поддержку неочевидных цветов и преобразуем один цвет в другой.

Время чтения: 6 мин

Новая CSS-функция color() позволяет по-новому указывать значение цвета.

Можно использовать как значение для любых свойств, где нужен цвет. Например, color, border-color или accent-color.

У функции два способа использования:

  • абсолютное значение для указания цвета в цветовой области, отличной от sRGB;
  • относительное значение для перевода цвета из одного цветового пространства в другое.

Абсолютное значение

Скопировано

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

Например, цвета из пространства DCI-P3 (коротко P3) можно указать через эту функцию с параметром display-p3. P3-цвета можно указывать и через другие функции, например, oklch() (подробнее об этом в статье про OKLCH), однако способ с color() проще и нагляднее. Так записывается аналог цвета #00bbff:

        
          
          .block {  background-color: color(display-p3 0 0.72 1);}
          .block {
  background-color: color(display-p3 0 0.72 1);
}

        
        
          
        
      

Если ваш монитор поддерживает пространство Display P3, то вы увидите разницу между левым (первым) и правым (вторым) блоками. Левый ярче, насыщеннее.

Открыть демо в новой вкладке

Параметры для абсолютного значения

Скопировано

Параметры функции color() для абсолютного значения:

  1. Цветовое пространство. Ключевое слово для нужного спектра:
  • srgb;
  • srgb-linear;
  • display-p3;
  • a98-rgb;
  • prophoto-rgb;
  • rec2020;
  • xyz;
  • xyz-d50;
  • xyz-d65.
  1. Компоненты цвета. Цвет, выраженный в трёх значениях.
  2. Альфа-канал (необязательное значение). Позволяет задавать прозрачность цвета. Указывается через слэш /.

Спектры и компоненты цвета

Скопировано

Укажем цветовое пространство a98-rgb и компоненты цвета 0.29, 0.73 и 1.

        
          
          .block {  background-color: color(a98-rgb 0.29 0.73 1);}
          .block {
  background-color: color(a98-rgb 0.29 0.73 1);
}

        
        
          
        
      

Тот же цвет в пространстве srgb-linear с компонентами 0, 0.5 и 1.

        
          
          .block {  background-color: color(srgb-linear 0 0.5 1);}
          .block {
  background-color: color(srgb-linear 0 0.5 1);
}

        
        
          
        
      

Альфа-канал

Скопировано

Добавим всем цветам альфа-канал со значением 0.5, сделаем цвет полупрозрачным:

        
          
          .block-1 {  background-color: color(display-p3 0 0.72 1 / 0.5);}.block-2 {  background-color: color(a98-rgb 0.29 0.73 1 / 0.5);}.block-3 {  background-color: color(srgb-linear 0 0.5 1 / 0.5);}
          .block-1 {
  background-color: color(display-p3 0 0.72 1 / 0.5);
}

.block-2 {
  background-color: color(a98-rgb 0.29 0.73 1 / 0.5);
}

.block-3 {
  background-color: color(srgb-linear 0 0.5 1 / 0.5);
}

        
        
          
        
      
Открыть демо в новой вкладке

Относительное значение

Скопировано

Относительное значение пригодится для преобразования цвета или его перевода из одного цветового пространства в другое.

Параметры для относительного значения

Скопировано

Параметры функции color():

  1. from плюс оригинальный цвет. Для относительного значения обязательно писать ключевое слово и цвет, который хотим преобразовать.
  2. Цветовое пространство. Ключевое слово, указывающее в какое из цветовых пространств переводим цвет:
  • srgb;
  • srgb-linear;
  • display-p3;
  • a98-rgb;
  • prophoto-rgb;
  • rec2020;
  • xyz;
  • xyz-d50;
  • xyz-d65.
  1. Компоненты цвета. Три канала для обозначения цвета в виде числа или строки текста.
  2. Альфа-канал (необязательное значение). В нём указываете прозрачность цвета через слэш /.

Цветовые пространства и компоненты

Скопировано

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

  • r, g и b: для цветовых пространств srgb, srgb-linear, display-p3, a98-rgb, prophoto-rgb и rec2020.
  • x, y и z: для цветовых пространств xyz, xyz-d50 и xyz-d65.

Если в исходном цвете есть альфа-канал, то за него отвечает слово alpha.

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

Скопировано

Переведём цвет hotpink в цветовое пространство display-p3 и добавим прозрачность 0.8:

        
          
          .block {  background-color: color(from hotpink display-p3 r g b / 0.8);}
          .block {
  background-color: color(from hotpink display-p3 r g b / 0.8);
}

        
        
          
        
      

Изменение компонентов цвета

Скопировано

Переведём тот же цвет в пространство a98-rgb. Первый компонент r оставим неизменным, второй g заменим на 1, а третий b — на 0:

        
          
          .block {  background-color: color(from hotpink a98-rgb r 1 0 / 0.8);}
          .block {
  background-color: color(from hotpink a98-rgb r 1 0 / 0.8);
}

        
        
          
        
      

Если хотите, можете заменить два, три или все четыре компонента цвета и получить совершенно новый цвет. Но тогда встаёт вопрос: зачем такие сложности?

calc() для вычислений

Скопировано

Можно использовать функцию calc() для вычислений внутри color(). Переведём всё тот же seagreen в пространство xyz, к каждому из компонентов прибавим по 0.3.

        
          
          .block {  background-color: color(from hotpink xyz calc(x + 0.3) calc(y + 0.3) calc(z + 0.3));}
          .block {
  background-color: color(from hotpink xyz calc(x + 0.3) calc(y + 0.3) calc(z + 0.3));
}

        
        
          
        
      

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

Открыть демо в новой вкладке

Пропущенный компонент

Скопировано

Вместо компонента цвета можно использовать ключевое слово none. Браузер сам подставит вместо него 0 с нужными единицами измерения.

Эти две записи приведут к одному результату:

        
          
          .block {  color: color(display-p3 0 0.72 1 / 0.5);  background-color: color(display-p3 none 0.72 1 / 0.5);}
          .block {
  color: color(display-p3 0 0.72 1 / 0.5);
  background-color: color(display-p3 none 0.72 1 / 0.5);
}

        
        
          
        
      

И в этом случае цвет получится одинаковым:

        
          
          .block {  color: color(from hsl(none 100% 50%) srgb r g b / 0.8);  background-color: color(from hsl(0deg 100% 50%) srgb r g b / 0.8);}
          .block {
  color: color(from hsl(none 100% 50%) srgb r g b / 0.8);
  background-color: color(from hsl(0deg 100% 50%) srgb r g b / 0.8);
}

        
        
          
        
      

Использование кастомных свойств

Скопировано

Чаще всего в проектах набор цветов хранится в виде переменных. Внутри функции color() можно использовать кастомные свойства.

Предположим, что есть набор из трёх цветов, и нужно добавить каждому из них альфа-канал:

        
          
          :root {  --text-color: white;  --background-color: #2E9AFF;  --accent-color: hsl(346 81% 78%);}.block {  color: color(from var(--text-color) srgb r g b / 0.9);  border: 1px solid color(from var(--accent-color) display-p3 r g b / 0.75);  background-color: color(from var(--background-color) xyz x y z / 0.2);}
          :root {
  --text-color: white;
  --background-color: #2E9AFF;
  --accent-color: hsl(346 81% 78%);
}

.block {
  color: color(from var(--text-color) srgb r g b / 0.9);
  border: 1px solid color(from var(--accent-color) display-p3 r g b / 0.75);
  background-color: color(from var(--background-color) xyz x y z / 0.2);
}

        
        
          
        
      
Открыть демо в новой вкладке

Проверка поддержки

Скопировано

Функция color() достаточно новая, поэтому не забывайте про поддержку браузерами и проверяйте её на Can I use.

Прогрессивное улучшение

Скопировано

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

        
          
          .block {  color: hotpink;}@supports(color: color(display-p3 0.93 0.45 0.7)) {  .block {    color: color(display-p3 0.93 0.45 0.7);  }}
          .block {
  color: hotpink;
}

@supports(color: color(display-p3 0.93 0.45 0.7)) {
  .block {
    color: color(display-p3 0.93 0.45 0.7);
  }
}

        
        
          
        
      

Директива @media с условием color-gamut поможет проверить поддержку цветового пространства:

        
          
          .block {  color: hotpink;}@media (color-gamut: p3) {  .block {    color: color(display-p3 0.93 0.45 0.7);  }}
          .block {
  color: hotpink;
}

@media (color-gamut: p3) {
  .block {
    color: color(display-p3 0.93 0.45 0.7);
  }
}

        
        
          
        
      

Постепенная деградация

Скопировано

Можно пойти с другого конца и изначально всем показывать цвет, записанный через color(). А если синтаксис не поддерживается, то показывать цвет без color().

        
          
          .block {  color: hotpink;  color: color(display-p3 0.93 0.45 0.7);}
          .block {
  color: hotpink;
  color: color(display-p3 0.93 0.45 0.7);
}

        
        
          
        
      

В примере выше, если браузер умеет читать color(), применится второе правило, поскольку оно ниже по коду. Если браузер с ним не знаком, он откинет его и применит расположенное выше правило с цветом hotpink.