Год назад я писал о том, что рабочая группа CSS приняла решение о добавлении функции if(). В недавно вышедшей 137й версии Chrome и Edge появилась поддержка if(). Хотя я скептически отношусь к этому нововведению, оно стоит внимания.
Функция
if() позволяет задавать разные значения свойств в зависимости от условий или резервное значение, если ни одно из условий не выполняется. Количество условий не ограничено, а резервное значение не обязательно. Базовый синтаксис такой:selector {
property: if(
condition-1: value-1;
condition-2: value-2;
else: value-3
);
}На данный момент в качестве условия можно применить одну из трёх функций:
-
media() — привычные медиа-запросы, аналогичные директиве @media;-
supports() — запросы поддержки функций, аналогичные директиве @supports;-
style() — запросы стиля, которые недавно стали доступны в рамках директивы @container.Синтаксис функции
if() заменяет директивы @media, @supports и @container в тех случаях, когда нужно использовать другие значения отдельных свойств при выполнении условия директивы. С if() код получается короче:/* Подход с переопределением */
.card {
padding: 2rem;
}
@media (width < 600px) {
.card {
padding: 1rem;
}
}
/* Подход с вложенностью */
.card {
padding: 2rem;
@media (width < 600px) {
padding: 1rem;
}
}
/* Подход с if() */
.card {
padding: if(
media(width < 600px): 1rem; else: 2rem
);
}
Наиболее интересна функция
style(), которая позволяет проверять значения стандартных и пользовательских свойств. Так, в зависимости от цвета текста можно менять иконку в компоненте, вроде тоста, примечания или уведомления:.toast {
background-image: if(
style(color: green): url('/success.svg');
style(color: orange): url('/warning.svg');
style(color: red): url('/danger.svg');
else: url('/info.svg')
);
}
.toast--success {
color: green;
}
.toast--warning {
color: orange;
}
.toast--danger {
color: red;
}Все иконки указаны в одном месте и зависят от цвета текста. В противном случае определять иконки нужно у каждого класса-модификатора. Объём кода в обоих случаях будет плюс-минус сопоставимым, но с
if() иконки описаны в одном месте.UPD 03.08.25: style() может принимать обычные свойства, но пока поддерживаются только пользовательские свойства. Пример выше не будет работать.
Пользовательские свойства позволяют определять произвольные характеристики элементов и их значения. Это можно использовать в сочетании с функцией
if() для создания различных вариантов компонентов с разными стилями:.toast {
background-image: if(
style(--variant: success): url('/success.svg');
style(--variant: warning): url('/warning.svg');
style(--variant: danger): url('/danger.svg');
else: url('/info.svg')
);
color: if(
style(--variant: success): green;
style(--variant: warning): orange;
style(--variant: danger): red;
else: lightblue
);
}
.toast--success {
--variant: success;
}
.toast--warning {
--variant: warning;
}
.toast--danger {
--variant: danger;
}Все стили тоста определяются в одном месте, а модификаторы задают только значения пользовательского свойства. Это чем-то похоже на пропсы во фреймворках. С
if() и обновлённой функцией attr() можно обойтись без модификаторов:<style>
.toast {
--variant: attr(data-variant type(<custom-ident>), default);
/* свойства с if() */
}
</style>
<!-- установка --variant через атрибут style -->
<div class="toast" style="--variant: danger">
<!-- danger тост -->
</div>
<!-- установка --variant через data-атрибут -->
<div class="toast" data-variant="success">
<!-- success тост -->
</div>
Несмотря на мой скепсис по поводу
if(), стилизация компонентов с указанием пользовательских свойств в style или data-* атрибутах и проверкой их значений в одном месте выглядит интересно.Так как синтаксис
if() можно откатить к директивам @media, @supports и @container, его уже скоро можно будет использовать в сочетании с PostCSS или LightningCSS. Пока в них нет соответствующих преобразований, но это лишь вопрос времени.#css