Когда говорим «динамический», подразумеваем JavaScript. Но некоторые динамические функции можно реализовать, используя только CSS. Например, цвета. 

С помощью прозрачности

Возможно, вы уже знаете, как создавать цвета с помощью пользовательских свойств CSS и альфа-канала. Освежим память: 

:root {
--color: 255 255 0;
}
.selector {
background-color: rgb(var(--color) / 0.5);
}

Код выше — самый простой для создания пользовательских свойств цвета, но несовершенный. Нужно определить свойство color в цветовом пространстве, которое поддерживает альфа-канал:  rgb(), rgba(), hsla().

:root {
--color-rgb: 255 255 0;
--color-hsl: 5 30% 20%;
}
.selector {
background-color: rgb(var(--color-rgb) / 0.5);
background-color: hsl(var(--color-hsl) / 0.5);
}

Таким образом, вы не переключать значение цвета пользовательского свойства с одного типа на другой. Обычно про такое пишут в JavaScript, там используется приведение типов. Но вот как это выглядит в CSS:

:root {
--color: #fa0000;
}
.selector {
/*
Trying to convert a HEX color to an RGB one doesn't work
This snippet will not work. this just return a blank white background
*/
background-color: rgb(var(--color) / 0.5);
}

С учётом сказанного, на самом деле невозможно использовать значения цветов HEX для динамических цветов в CSS. Даже указать альфа-канал для цвета HEX, как #FA000060, можно только декларативно, ведь в CSS нет конкатенации:

:root {
--color: #fa0000;
}
.selector {
/* You can’t dynamically specify the alpha channel. This will still not do anything */
background-color: var(--color) + "60";
}

Можно объявить значение пользовательского свойства, используя любой цветовой тип:  rgb, rgba, hsla, hsl, hex. И уже этот тип с лёгкостью преобразуется в любой другой. Пример управления динамическими цветами:

/* - - - - - - - - - - - - Using hex Colors - - - - - - - - - - - - - - */
:root {
  --color: #fa0000;
}
.selector {
  /* can’t do this */
  background-color: rgb(var(--color) / 0.5);
  /* can do this */
  background-color: rgb(from var(--color) r g b / .5);
}

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

/* - - - - - - - - - - - - Using Named Colors - - - - - - - - - - - - - - */
:root {
  --color: red;
}
.selector {  
  background-color: rgb(from var(--color) r g b / .5);
}

С помощью функции calc()

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

:root {
  /* Define individual channels of a specific color */
  --color-h: 0;
  --color-s: 100%;
  --color-l: 50%;
}
.selector {
  /* Dynamically change individual channels */
  color: hsl(
    var(--color-h),
    calc(var(--color-s) - 10%),
    var(--color-l)
  );
}

Но от этого код удлиняется, а значения HEX всё равно не поддерживаются. Решение — функция calc():

:root {
  --color: #ff0000;
}
.selector {  
  color: hsl(from var(--color) h calc(s - 10%) l);
}

С помощью значения фильтра

Функция filter: brightness(x%) динамически изменяет значения цвета в процентах. Минус метода в том, что функция влияет на конкретный элемент. То есть некоторые части страницы могут отличаться друг от друга.


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

Комментарии (4)


  1. p07a1330
    18.11.2022 18:37

    Минус метода в том, что функция влияет на конкретный элемент.

    А еще - в том что он сильно бъет по производительности
    Вообще, фильтры эта та штука, которую иногда приходится применять - но нужно стараться избегать,, особенно при таргетировании на малопроизводильные устройства


  1. grobitto
    18.11.2022 18:47
    +6

    Очень плохой перевод. Еще и вырезали пояснения из оригинального текста


  1. MaryRabinovich
    19.11.2022 21:57

    Мне кажется, автор назвал "динамическим" что-то попросту вычисляемое. Т.е., как получить цвета, не заранее заданные напрямую, а дополнительно вычисленные.

    Но одноразово вычисленные же?

    Всё таки на Javascript под динамикой понимается, кмк, разное вычисление. Не то, чтобы непредсказуемое, но с возможностью динамически (то же самое слово, и на мой слух оно тут куда уместнее) изменять параметры вычисления.


    1. grobitto
      21.11.2022 12:48

      В оригинале у автора было пояснение, что это кейс где цвета задаются где-то снаружи (например из админки), и ты не имеешь к ним доступа. Ну и надо сделать из базового цвета цвет ховера, например. У него там в оригинале еще одна глава, что это очень легко делается на SCSS, но переводчик устал и решил что так сойдет