CSS давно подвергается критике из за отсутствия условной логики (if...else). Хотя мы разработали хитроумные обходные пути с использованием @media запросов (media queries), переключаемых настраиваемых свойств и контейнерных запросов, эти решения часто кажутся слишком громоздкими и непрямыми. Рабочая группа CSS (CSS Working Group) одобрила функцию if() для разработки, которая обещает добавить настоящую условную стилизацию непосредственно в наши стили.

css
css

Раньше, когда нам требовались условные стили, мы использовали такие подходы как:

  • @media запросы на основе специфичных условий

  • Изменение свойств с помощью calc() и clamp()

  • @container запросы, основанные на свойствах родительского элемента

  • Множественные селекторы с разной специфичностью

Функция if() заменяет эти шаблоны, предоставляя более удобный декларативный способ применения различных значений в зависимости от конкретных условий.

Вместо написания отдельных блоков правил или сложных вычислений мы можем выразить условную логику непосредственно в объявлениях свойств:

Атрибут

Традиционный CSS (блоки @media)

Функция if()

Syntax

@media (condition) {

 .selector { property: value; } 

}

property: if(condition: value; else: fallback);

Организация кода

Фрагментированная - логика разбросана по нескольким блокам @media

Централизованная - вся условная логика собрана в одном месте

Рефакторинг (Maintainability)

Изменения требуют обновления нескольких блоков правил

Единая точка изменения для каждого свойства

Скорость обучения

Знакомый шаблон для разработчиков

Новый синтаксис требует изучения условных шаблонов

Поддержка браузеров

Универсальный - поддерживается в современных браузерах

Ограниченная поддержка в браузерах

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

Примечание: Оригинальный пост в последний раз обновлялся в октябре 2025 года Temitope Oyedele, чтобы отразить актуальную поддержку браузеров, предложить запасные стратегии для прогрессивного улучшения и рассмотреть, как функция CSS if() может сформировать будущие системы дизайна.

TL;DR

Функция CSS if() вводит настоящую условную логику в CSS. Она позволяет писать условия в строке, вместо того чтобы полагаться на @media запросы или обходные пути:

  • Работает с запросами style(), media() и support() для тем, адаптивных настроек и стилей на основе состояния.

  • Позволяет работать на уровне свойств элемента, в то время как @media и @containerзапросы по-прежнему обрабатывают более широкую область макета.

  • Поддерживает вложенную логику и хорошо сочетается с calc() для расширенных шаблонов.

  • В настоящее время поддерживается только в браузерах Chromium, поэтому используйте прогрессивное улучшение и проверки @supports.

Синтаксис if()

Функция if() имеет структуру, которая может показаться знакомой, если вы работали с условными операторами в языках программирования, но она разработана специально для декларативного характера CSS. Давайте разберем, как она работает, шаг за шагом.

Базовая структура if()

Базовый синтаксис функции:

property: if(condition-1: value-1; condition-2: value-2; else: fallback);

Обратите внимание на несколько важных деталей.

  1. Функция начинается с if, за которым сразу следует открывающая скобка без пробела.

  2. Каждая пара «условие-значение» condition-1: value-1; разделяется точкой с запятой, а не запятой, что отличает её от других функций CSS.

  3. Условие else служит резервным значением, если ни одно из условий не выполняется.

Вот простой пример, иллюстрирующий основную концепцию:

/* Применить разные размеры кнопок в зависимости от типа устройства ввода */
button {
  width: if(media(any-pointer: fine): 30px; else: 44px);
}

Это правило гласит: «Если у устройства есть точный указатель (например, мышь), сделать ширину кнопки 30 пикселей; иначе сделать ширину 44 пикселя для сенсорных интерфейсов».

Три типа запросов style(), media() и support()

Функция if() поддерживает три типа запросов, каждый из которых обслуживает разные типы условий. Их можно рассматривать как разные «типы вопросов», которые можно задать о текущем контексте.

style() запросы

Они проверяют значения CSS-переменных или вычисляемых свойств для текущего элемента:

.card {
  background: if(style(--variant): var(--primary); else: white);
}

Данное условие проверяет, есть ли у элемента .card переменная --variant с каким-либо значением. Если да, то использовать --primary цвет; если нет, то использовать цвет white:

style() запросы
style() запросы

media() запросы

Они работают так же, как и традиционные @media запросы, но их можно применять внутри свойств :

.sidebar {
  width: if(media(min-width: 768px): 300px; else: 100%);
}

Такого рода внутренние @media запросы, заменяют то, что традиционно требовало бы отдельного блока CSS правил @media {...}.

supports() запросы

Они проверяют поддержку функций CSS:

/* Резервный вариант для браузеров, не поддерживающих CSS Grid. */
.grid-container {
  display: if(supports(display: grid): grid; else: flex);
}

Требования к синтаксису функции if()

Функция if() имеет особые синтаксические требования, отличающиеся от других функций CSS.

Во-первых, между if и открывающей скобкой нет пробела. Это отличается от функций типа calc(), где пробелы более гибкие:

/* Правильно */
width: if(media(min-width: 768px): 300px; else: 100px);

/* Неправильно */
width: if (media(min-width: 768px): 300px; else: 100px);

Во-вторых, каждая пара «условие-значение» разделяется точкой с запятой, а не запятой:

/* Правильно */
color: if(
  style(--theme: dark): white;
  style(--theme: light): black;
  else: gray
);

/* Неправильно */
color: if(
  style(--theme: dark): white,
  style(--theme: light): black,
  else: gray
);

Эти синтаксические правила существуют, поскольку функция if() должна анализировать несколько пар «условие-значение» в рамках одного вызова функции. Разделитель в виде точки с запятой помогает парсеру CSS различать конец одного условия и начало другого, особенно при работе со сложными значениями, которые могут содержать запятые.

if() в сравнении с современными подходами CSS

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

if() в сравнении с @media запросами

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

Рассмотрим традиционный подход к созданию сенсорных кнопок:

/* Традиционный подход к медиа-запросам */
button {
  width: 30px;
  height: 30px;
  padding: 8px;
}

@media (any-pointer: coarse) {
  button {
    width: 44px;
    height: 44px;
    padding: 12px;
  }
}

Это работает, но обратите внимание, что адаптивное поведение кнопки разделено на два отдельных блока правил. Если вы хотите понять, как эта кнопка адаптируется к разным методам ввода, вам нужно мысленно объединить эти правила.

Вот та же логика с использованием функции if():

/* Метод с if() - вся логика в одном месте */
button {
  width: if(media(any-pointer: coarse): 44px; else: 30px);
  height: if(media(any-pointer: coarse): 44px; else: 30px);
  padding: if(media(any-pointer: coarse): 12px; else: 8px);
}

Подход с if() сохраняет всю адаптивную логику в рамках каждого свойства. Это позволяет сразу понять, как каждое свойство реагирует на различные условия. Сразу видно, что эта кнопка увеличивается на сенсорных устройствах по всем направлениям:

if() в сравнении с @media запросами
if() в сравнении с @media запросами

Однако это не всегда лучше @media запросов. Если вам нужно изменить множество свойств одновременно, блок @media запросов может быть более читабельным и эффективным. Ключ к успеху - понимать, когда и какой подход лучше подходит для вашего кода.

if() в сравнении с @container запросами

@container запросы позволяют применять стили, основанные на вычисленных стилях родительского контейнера. Это мощный инструмент для компонентного проектирования, но он работает иначе, чем функция if(), с точки зрения расположения логики.

Рассмотрим компонент карточки, внешний вид которого меняется в зависимости от темы его контейнера:

/* Метод @container запросов */
.theme-container {
  --theme: dark;
}

@container style(--theme: dark) {
  .card {
    background: #333;
    color: white;
  }
}

@container style(--theme: light) {
  .card {
    background: white;
    color: black;
  }
}

Этот подход требует определения логики на уровне контейнера, а стили применяются каскадно и через наследование. Контейнер «транслирует» состояние своей темы своим потомкам.

С помощью функции if() логика перемещается непосредственно в сам элемент:

/* if() Метод - автономная, внутренняя логика */
.card {
  background: if(
    style(--theme: dark): #333;
    style(--theme: light): white;
    else: #f5f5f5
  );
  color: if(
    style(--theme: dark): white;
    style(--theme: light): black;
    else: #888
  );
}

Такой подход делает настройку тем для .card автономной. Карточке не нужно знать логику запросов её контейнера; она просто проверяет наличие CSS-переменных, связанных с темой, у себя:

if() в сравнении с @container запросами
if() в сравнении с @container запросами

Разница небольшая, но важная. @container запросы хорошо подходят, когда нужно установить контекст для нескольких дочерних элементов. Функция if() хорошо подходит, когда нужно, чтобы каждый элемент отвечал за своё собственное условное поведение.

if() в сравнении с CSS-переменными ("Переключатели" | toggles)

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

Вот типичный пример использования переключений в CSS-переменных:

/* Метод переключения CSS-переменных */
.button {
  --is-primary: ; /* undefined, по умолчанию переменная не установлена */
  --primary-bg: var(--is-primary, transparent);
  --primary-color: var(--is-primary, currentColor);

  background: var(--primary-bg, var(--blue-500));
  color: var(--primary-color, white);
}

.button--primary {
  --is-primary: initial; /* переменная установлена, запускает "переключатель"  */
}

Этот приём работает, эксплуатируя резервное поведение CSS. Если --is-primary не определено, в свойствах используются резервные значения. Если же оно определено (даже как initial), применяются основные значения.

Несмотря на свою продуманность, этот подход имеет ряд недостатков. Логика непрямая и может быть сложной для понимания, особенно разработчикам, не знакомым с этой техникой. Кроме того, он не читается естественно, поскольку для понимания происходящего необходимо понимать концепцию «toggle» (переключатель).

Функция if() делает эту же логику явной и читабельной:

/* Метод if() - четкая условная логика */
.button {
  background: if(
    style(--variant: primary): var(--blue-500);
    else: transparent
  );
  color: if(
    style(--variant: primary): white;
    else: currentColor
  );
}

В этой версии четко сформулировано ее назначение: «если вариант является основным, использовать эти цвета; в противном случае использовать эти значения по умолчанию», что делает условную логику явной и само документируемой:

if() в сравнении с CSS-переменными ("Переключатели" | toggles)
if() в сравнении с CSS-переменными ("Переключатели" | toggles)

Понимание этих сравнений поможет вам выбрать правильный инструмент для каждой ситуации. Иногда вам понадобится каскадное поведение @container запросов, иногда - широкий спектр @media запросов, а иногда - явная логика функции if(). Ключ к успеху - понять, какой подход лучше всего подходит для вашего конкретного случая использования и дальнейшей эксплуатации проекта.

Практические примеры

Теперь, когда мы понимаем синтаксис и преимущества функции if(), давайте посмотрим, как она работает на практике.

Наверх к Теории

Темы

Дизайн-системам часто требуется поддерживать несколько тем, сохраняя при этом согласованность между компонентами. Традиционный подход требует либо дублирования CSS-правил, либо сложных каскадов CSS-переменных. Функция if() превращает эту задачу в элегантное решение, сохраняя логику темы централизованной и гибкой.

Рассмотрим дизайн-систему, поддерживающую три темы: «Ocean», «Forest» и «Default». Вместо создания отдельных CSS-файлов или сложных сопоставлений переменных мы можем определить цвета темы условно:

/* Компоненты тем с использованием if() */
.card {
  background: if(
    style(--theme: ocean): #f0f8ff;
    style(--theme: forest): #f5fffa;
    else: #ffffff
  );
  border: 2px solid if(
    style(--theme: ocean): #0077be;
    style(--theme: forest): #228b22;
    else: #333333
  );
  color: if(
    style(--theme: ocean): #0077be;
    style(--theme: forest): #228b22;
    else: #333333
  );
}

.button {
  background: if(
    style(--theme: ocean): #0077be;
    style(--theme: forest): #228b22;
    else: #333333
  );
  color: if(
    style(--theme: ocean): #f0f8ff;
    style(--theme: forest): #f5fffa;
    else: #ffffff
  );
  border: none;
  padding: 12px 24px;
  border-radius: 6px;
}

Чтобы активировать тему, просто установите CSS-переменную для любого контейнера:

.ocean-theme { --theme: ocean; }
.forest-theme { --theme: forest; }
Применение if() с темами
Применение if() с темами

Такой подход создаёт мощный каскадный эффект. При установке --theme: ocean для контейнера .card все дочерние элементы автоматически получают цвета морской тематики через систему CSS-переменных. Функция if() выполняется один раз для каждого элемента, проверяя свойство --theme и применяя соответствующие значения цветов.

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

Адаптивные компоненты

В то время как @media запросы отлично справляются с изменением макета в зависимости от размера области просмотра, функция if() идеально подходит для создания компонентов, адаптирующихся к различным контекстам взаимодействия. Это выходит за рамки традиционного адаптивного дизайна и позволяет создавать по-настоящему адаптивные интерфейсы.

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

/* Адаптивная навигация, реагирующая на различные контексты */
.nav-item {
  /* Базовые размеры адаптируются к методу взаимодействия */
  min-height: if(
    media(any-pointer: coarse): 44px;    /* Touch-friendly minimum */
    media(any-pointer: fine): 32px;      /* Mouse-optimized */
    else: 36px                           /* Безопасный запасной вариант */
  );

  /* Padding масштабируются с учетом доступного пространства и способа ввода */
  padding: if(
    media(any-pointer: coarse) and media(min-width: 768px): 16px 24px;
    media(any-pointer: coarse): 12px 16px;
    media(min-width: 768px): 8px 16px;
    else: 6px 12px
  );

  /* Размер шрифта учитывает размер экрана и требования к читаемости */
  font-size: if(
    media(min-width: 1024px): 16px;
    media(min-width: 768px): 15px;
    media(any-pointer: coarse): 16px;    /* Больше для сенсорного экрана */
    else: 14px
  );
}

/* Hover, учитывающий предпочтения пользователя */
.nav-item:hover {
  background: if( /* Только на устройствах с функцией наведения курсора */
    media(hover: hover): var(--primary-light); 
    else: transparent
  );
}

Этот компонент навигации демонстрирует прогрессивное улучшение благодаря условному стилю. Он учитывает способ ввода пользователя (сенсорный экран или мышь), доступное пространство на экране и возможности устройства, чтобы создать наиболее удобный интерфейс:

Responsitive components (Адаптивные компоненты)
Responsitive components (Адаптивные компоненты)

Обратите внимание, как условия дополняют друг друга. Компонент сначала проверяет наличие сенсорного ввода и соответствующим образом корректирует размер, а затем корректирует свои решения, исходя из доступного пространства на экране. Это создаёт тонкую адаптивную систему, которая выходит за рамки простых контрольных точек и учитывает реальный пользовательский контекст.

Стили на основе состояния

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

Давайте создадим форму, которая обеспечивает расширенную визуальную обратную связь на основе состояния проверки:

/* Стили для формы с учетом состояния и визуальной обратной связью */
.form-input {
  /* Базовые стили не меняются */
  padding: 12px 16px;
  border-radius: 6px;
  font-size: 16px;
  transition: all 0.2s ease;

  /* Border color отражает состояние проверки. */
  border: 2px solid if(
    style(--state: error): #dc3545;
    style(--state: success): #28a745;
    style(--state: warning): #ffc107;
    style(--state: focus): #007bff;
    else: #dee2e6
  );

  /* Background color обеспечивает мягкую индикацию состояния */
  background: if(
    style(--state: error): #fff5f5;
    style(--state: success): #f0fff4;
    style(--state: warning): #fffbf0;
    else: #ffffff
  );

  /* Icon color координируется с состоянием */
  --icon-color: if(
    style(--state: error): #dc3545;
    style(--state: success): #28a745;
    style(--state: warning): #ffc107;
    else: #6c757d
  );
}

/* Значки состояния, отображаются в зависимости от условий */
.form-input::after {
  content: if(
    style(--state: error): "❌";
    style(--state: success): "✅";
    style(--state: warning): "⚠️";
    else: ""
  );
  color: var(--icon-color);
  margin-left: 8px;
}

/* Состояние загрузки с анимированным стилем */
.form-input {
  /* Анимированный border для состояния загрузки */
  border-style: if(
    style(--state: loading): dashed;
    else: solid
  );

  /* Уменьшение непрозрачности во время загрузки */
  opacity: if(
    style(--state: loading): 0.7;
    else: 1
  );
}

Чтобы управлять этими состояниями, вы должны устанавливать CSS-переменную с помощью JavaScript:

// input которому нужно назначить состояние
const input = document.querySelector('.form-input');

// Set error state
input.style.setProperty('--state', 'error');

// Set success state
input.style.setProperty('--state', 'success');

// Clear state
input.style.removeProperty('--state');
if() state form controls
if() state form controls

Этот шаблон создаёт чёткое разделение между логикой состояния (управляемой JavaScript) и визуальным представлением (обрабатываемым CSS). Функция if() служит связующим звеном между этими задачами, преобразуя значения состояния в соответствующие визуальные стили.

Продвинутые методы

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

Вложенные функции if()

Реальные возможности функции if() раскрываются, когда мы вкладываем условия друг в друга. Это создаёт деревья решений, способные обрабатывать несколько уровней логики, подобно тому, как это происходит на языке программирования, но с использованием декларативного синтаксиса CSS.

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

/* Расширенный вложенный if() для всесторонней адаптации входных данных.
***
Опция prefers-reduced-motion: no-preference | reduce
может использоваться для определения, запросил ли пользователь,
чтобы ОС минимизировала количество анимации или движения, которые она использует:
reduce - да
no-preference - не установлена (по умолчанию) */
.form-input {
  /* Сложная логика расчета размера, учитывающая множество факторов */
  font-size: if(
    /* Проверим, предпочитает ли пользователь большой размер шрифта */
    media(prefers-reduced-motion: no-preference) and style(--size: large): if(
      /* Делаем поправку на тип устройства */
      media(any-pointer: coarse): 20px;    /* Крупный текст для тачскрина */
      else: 18px                           /* Крупный текст для остальных */
    );

    /* Не предпочитает большой размер шрифта, но включено снижение анимаций */
    media(prefers-reduced-motion: reduce): if(
      /* Пользователям с включеным снижением анимаций */
      media(any-pointer: coarse): 18px;    /* Размер для тачскрина */
      else: 16px                           /* Размер для остальных */
    );

    /* Обычный режим со стандартными настройками */
    else: if(
      media(any-pointer: coarse): 17px;    /* Стандартный тачскрин */
      else: 15px                           /* Стандартный для остальных */
    )
  );

  /* Padding который адаптируется как к состоянию, так и к контексту */
  padding: if(
    /* Для Error state требуется дополнительное пространство для визуального акцента */
    style(--state: error): if(
      media(any-pointer: coarse): 16px 20px;  /* Больше места для тачскрина */
      else: 12px 16px                         /* Стандартные отступы для остальных */
    );

    /* Success state может быть более компактным */
    style(--state: success): if(
      media(any-pointer: coarse): 14px 18px;
      else: 10px 14px
    );

    /* Для остальных варинатов используются базовые отступы */
    else: if(
      media(any-pointer: coarse): 12px 16px;
      else: 8px 12px
    )
  );
}

Вложенная структура создаёт иерархию решений. Внешняя функция if() обрабатывает первичное услови�� (настройки ос/браузера или предпочтения пользователя), а внутренние функции if() обрабатывают вторичные условия (типы устройств).

Это создает дерево решений, которое может обрабатывать сложные сценарии, оставаясь при этом удобочитаемым:

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

Ключевой момент здесь заключается в том, что вложенные функции if() позволяют создавать условную логику, отражающую реальный процесс принятия решений. Как и в случае с выражением «если пользователь предпочитает крупный текст, то подумайте, использует ли он сенсорное устройство», CSS может реализовать ту же логическую структуру.

Интеграция с calc()

Еще одной мощной комбинацией в продвинутом CSS является объединение функции if() с функцией calc() для динамических вычислений. Это особенно эффективно при работе с CSS-переменными, инициализированными с помощью @property, что позволяет им участвовать в вычислениях и анимации.

Давайте расширим наш навигационный компонент, включив в него расчет динамических размеров на основе доступного пространства экрана и плотности контента:

/* Регистрация пользовательских свойств для участия в расчетах */
@property --nav-items {
  syntax: '<number>';
  initial-value: 4;
  inherits: true;
}

@property --available-width {
  syntax: '<length>';
  initial-value: 100vw;
  inherits: false;
}

/* Расширенная навигация с вычисляемыми размерами элементов */
.nav-container {
  /* Расчет оптимального множителя в зависимости от содержимого и размера экрана */
  --spacing-multiplier: if(
    media(min-width: 1200px): 1.5;    /* Большой множитель для больших экранов */
    media(min-width: 768px): 1.2;     /* Средний множитель для средних экранов */
    media(any-pointer: coarse): 1.3;  /* Особый множитель для мобильных устройств */
    else: 1.0                         /* Компактный множитель по умолчанию  */
  );

  /* Динамический gap. Расчет в зависимости от условий */
  gap: calc(
    /* Базовое значение */
    16px * 
    /* Оптимальный множитель */
    var(--spacing-multiplier) *
    /* Отзывчивый коэффициент, расчитывается на основе доступной ширины экрана */
    if(
      media(min-width: 1200px): 1;
      media(min-width: 768px): 0.8;
      else: 0.6
    )
  );
}

.nav-item {
  /* Расчет базовой ширины элемента на основе количества элементов и условий */
  flex-basis: calc(
    /* Доступная ширина, деленная на количество элементов (@property) */
    (var(--available-width) / var(--nav-items)) *
    /* Корректирующий коэффициент в зависимости от размера экрана и типа устройства */
    if(
                          /* Меньший на большом Desktop'e (с точным курсором) */
      media(min-width: 1200px) and media(any-pointer: fine): 0.9;  
      media(min-width: 768px): 0.95;    /* Маленький на планшетах */
      media(any-pointer: coarse): 1.0;  /* Обычный на тачскринах */
      else: 0.85                        /* Компактный на маленьких экранах */
    )
  );
}

Этот шаблон демонстрирует, как условная логика может управлять математическими вычислениями. Функция if() предоставляет условные значения, а calc() выполняет динамические вычисления. Вместе они создают макеты, которые автоматически оптимизируются в зависимости от контекста:

Интеграция if() + calc()
Интеграция if() + calc()

Эффективность этого подхода становится очевидной, когда вы понимаете, что изменение CSS-переменной --nav-items мгновенно пересчитывает все отступы и размеры во всех контрольных точках и контекстах взаимодействия. Это создаёт по-настоящему адаптивные макеты, реагирующие как на изменения контента, так и на факторы окружения.

Частичные условные значения

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

Давайте улучшим компонент нашей карточки из раздела Тем, чтобы продемонстрировать эту технику:

/* Расширенная карта с условными сокращениями */
.card {
  /* Border с заданными шириной стилем и цветом */
  border: if(
    style(--emphasis: high): 4px solid #dc2626; /* Thick RED border для акцента */
    style(--emphasis: medium): 3px solid #f59e0b;  /* Medium ORANGE border */
    style(--emphasis: low): 2px dashed #10b981;    /* Dashed GREEN border */
    else: 1px solid #6b7280                        /* Standard GRAY border */
  );

  /* Тень от блока с условным размытием и распространением */
  box-shadow: 
    0 
    if(style(--elevation: high): 12px; else: 4px)    /* Условное смещение */
    if(style(--elevation: high): 32px; else: 12px)   /* Условное размытие */
    if(style(--elevation: high): 8px; else: 2px)     /* Условное распространение */
    if(style(--elevation: high): rgba(220, 38, 38, 0.3); else: rgba(0, 0, 0, 0.1));

  /* Заполнение условными горизонтальными и вертикальными значениями */
  padding: 
    if(style(--content: dense): 8px; else: 24px)     /* Условно вертикальный */
    if(style(--content: dense): 12px; else: 32px);   /* Условно горизонтальный */

  /* Фон с условным направлением градиента */
  background: linear-gradient(
    if(style(--direction: vertical): to bottom; else: to right),
    if(style(--gradient: subtle): #fef3c7; else: #ffffff),
    if(style(--gradient: subtle): #dbeafe; else: #ffffff)
  );
}

/* Кнопка внутри карточки, которая наследует и расширяет условную логику */
.card .button {
  /* Преобразование (transform), учитывающее состояние как карты, так и кнопки */
  transform: 
    scale(if(style(--state: active): 1.05; else: 1.0))
    translateY(if(
      style(--elevation: high): -2px; /* Увеличенный подъем на high elevation .cards */
      style(--state: active): -1px;   /* Небольшой подъем в активном состоянии */
      else: 0px
    ));
}

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

Сетка 3×3 карточек, демонстрирующая различные комбинации уровней акцента (высокий, средний, низкий), уровней возвышения (высокий, стандартный) и плотности контента (плотный, нормальный),
Сетка 3×3 карточек, демонстрирующая различные комбинации уровней акцента (высокий, средний, низкий), уровней возвышения (высокий, стандартный) и плотности контента (плотный, нормальный),

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

Поддержка в браузерах (на 10.2025)

По состоянию на октябрь 2025 года функция CSS if() поддерживается только в браузерах на базе Chromium (Chrome, Edge, Opera, Android WebView). Firefox и Safari всё ещё находятся в экспериментальном режиме.

Поддержка CSS if() на Октябрь 2025 года
Поддержка CSS if() на Октябрь 2025 года

Эта диаграмма показывает точные диапазоны версий для основных браузеров. Если вы планируете использоватьif() в production, вам следует сочетать его с резервными стратегиями.

Стратегии использования

Эти стратегии потребуют от вас использования базовой версии, работающей во всех браузерах, а затем добавления if() там, где она поддерживается. Для этого давайте рассмотрим несколько из следующих шаблонов:

Вначале -> стили по умолчанию

Вначале нужно начать с простых стилей, которые хорошо работают во всех браузерах. Затем добавить проверку @supports, которая улучшит эти стили для браузеров, совместимых с if():

/* Базовый уровень: безопасно во всех браузерах */
.alert {
  padding: 10px 14px;
  background: #fff7ed;
  color: #7c2d12;
  border: 1px solid #fdba74;
  border-radius: 4px;
}
 
/* Расширенная версия работает только если if() поддерживается */ 
@supports (border-radius: if(media(min-width: 640px): 8px; else: 4px)) { 
  .alert {
    border-radius: 
      if( 
        media(min-width: 1024px): 10px; 
        media(min-width: 640px): 8px; 
        else: 4px 
      );
    background: if(
      style(--level: critical): #fef2f2;
      else: #fff7ed
    );
    color: if(
      style(--level: critical): #7f1d1d;
      else: #7c2d12
    );
  }
}

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

Разделение на слои с @media запросами и @supports

Вы также можете комбинировать традиционные @media запросы с функцией if(). Вы позволяете @media запросам выполнять основную работу по внесению общих изменений, а затем используете if() для уточнения деталей.

/* Step 1: Базовый уровень */
.cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 12px 20px;
  background: #2563eb;
  color: white;
  border-radius: 6px;
}
/* Step 2: Более общее улучшение с помощью @media запроса */ 
@media (any-pointer: coarse) 
{ 
    .cta { padding: 14px 24px; min-height: 44px; } 
}

/* Step 3: Тонко настроенная логика, управляемая if() */
@supports (padding: if(media(any-pointer: coarse): 16px; else: 12px)) 
{ 
    .cta {  padding: if( 
                    media(any-pointer: coarse) and media(min-width: 768px): 16px 28px; 
                    media(any-pointer: coarse): 14px 24px; 
                    media(min-width: 1280px): 12px 24px; 
                    else: 12px 20px 
                );

            box-shadow: if(
            media(hover: hover): 0 2px 8px rgba(0,0,0,.15);
            else: none
            );
    }
}

В данном случае @media запрос обеспечивает возможность использования сенсорных устройств для касаний (taps), немного увеличив элемент в размерах. Затем сверху применяется if() для регулировки отступов и добавления интерактивности при наведении курсора только в соответствующих местах.

CSS-переменные с резервными вариантами

Вы также можете реализовать улучшение, комбинируя if() с CSS-переменными. Для этого сначала определите безопасные значения по умолчанию, а затем переопределите их с помощью @supports запросов.

/* Базовые значения */
:root {
  --surface: #f8fafc;
  --text: #0f172a;
  --space: 8px;
  --radius: 6px;
}

.list {
  background: var(--surface);
  color: var(--text);
  gap: var(--space);
  border-radius: var(--radius);
  padding: 12px;
}

/* Более детализированные значения при поддержке if() */
@supports (gap: if(media(min-width: 600px): 12px; else: 8px)) {
  :root {
    --space: if(
      media(min-width: 1200px): 14px;
      media(min-width: 600px): 12px;
      else: 8px
    );

    --radius: if(
      media(min-width: 1200px): 10px;
      media(min-width: 600px): 8px;
      else: 6px
    );

    --surface: if(
      style(--brand: alt): #f1f5ff;
      else: #f8fafc
    );
    --text: if(
      style(--brand: alt): #1e1b4b;
      else: #0f172a
    );
  }
}

Благодаря этому шаблону все браузеры смогут интерпретировать значения по умолчанию, а поддерживающие if() браузеры смогут рассчитывать новые значения CSS-переменных «на лету». Ваш компонент также будет обновляться автоматически.

Взгляд в будущее

Функция if() может изменить то, как мы пишем CSS, когда её поддержка станет более широкой. Сегодня значительная часть условной логики обрабатывается вне CSS, часто с помощью фреймворков, ориентированных на утилиты, решений CSS-in-JS или препроцессоров. Благодаря if() большая часть этой логики может быть перенесена обратно в таблицы стилей. Вы описываете условия один раз, и браузер применяет правильные значения. Это означает меньше длинных цепочек утилит в разметке и более чистые шаблоны в целом.

Системы дизайна также выиграют от этого. Такие токены (переменные), как --space или --color-surface, часто требуют нескольких @media запросов для поддержания адаптивности. С помощью if() одно правило может описать, как эти токены реагируют на изменение размера экрана или темы. Это делает системный код короче и проще в поддержке, сохраняя при этом гибкость.

На уровне компонентов преимущество ещё более очевидно. Кнопка или карточка могут сохранять свою контейнерную логику рядом с базовыми стилями, не полагаясь на @container запросы или глобальные переопределения. Вам не нужно переключаться между файлами, чтобы понять, как она адаптируется, поскольку правила находятся рядом со свойствами, на которые они влияют.

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

Собственная условная стилизация подразумевает применение стилей к элементам на основе определенных условий непосредственно в механизме стилизации платформы, без использования JavaScript или внешних библиотек для самой условной логики.

В контексте веб-разработки недавним достижением CSS стало введение функций if()и @ifat-правил, которые обеспечивают собственную условную стилизацию.

Сказал ИИ от Google

Когда следует начинать использовать if()?

Заманчиво дождаться, пока все браузеры добавят поддержку, но это не обязательно. Функция if() уже сегодня может быть полезна в реальных проектах, если всё настроить грамотно. Рассматривайте её не как инструмент для «замены всего», а как расширение, которое работает, когда базовые функции уже реализованы.

Вот когда имеет смысл начать его использовать:

  • Вы можете написать базовые стили, которые выглядят отлично, даже если функция if() не распознаётся.

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

  • Ваша команда хорошо разбирается в прогрессивном улучшении и может визуально протестировать обе ветви.

  • У вас уже есть токены дизайна (CSS-переменные), поэтому if() подключается к пороговым значениям и значениям, которые вы определили.

  • Ваши инструменты сборки (PostCSS, сборщики, минификаторы, линтеры) не удаляют неизвестные функции CSS.

Заключение

Функция CSS if() представляет собой подход следующего уровня в том, как мы реализуем условную стилизацию, переходя от обходных путей и отдельных блоков правил к встроенной, явной логике.

Выбирайте if(), когда вам нужно реализовать условное поведение на уровне свойств, например, для систем тем, состояний компонентов или адаптивных свойств, которым выгодно сохранять встроенную логику. Используйте @media запросы для комплексного изменения макета и @container запросы, когда вам нужно координировать несколько дочерних элементов.

Реальное применение функции if() заключается в создании более интеллектуальных, самодостаточных компонентов, способных адаптироваться к контексту без внешнего вмешательства. Наши примеры вложенных условий, интеграции с calc() и условных операторов с частичным значением демонстрируют, как CSS может эволюционировать от статической стилизации к динамическим, контекстно-зависимым системам, которые вдумчиво реагируют на потребности пользователя, возможности устройства и состояние приложения.

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