Используйте @supports at-rule(@<at-rule name>) {…}, чтобы условно применять определенные правила или объявления CSS, только если браузер поддерживает определенное правило.
Оно может содержать правила целиком или использоваться вместе с вложенными стилями CSS, чтобы условно применять определенные объявления.
.foo {
background: var(--accent-color);
@supports at-rule(@property) {
background-image: var(--rainbow-gradient);
animation: sliding-rainbow 1s linear infinite;
}
}
НЕ используйте @supports at-rule(), чтобы условно применить только обнаруженное правило.
/* BAD: CSS already ignores rules the browser doesn't understand, so this is unnecessary */
@supports at-rule(@starting-style) {
@starting-style {
/* ... */
}
}
Определение поддержки at-правил, когда @supports at-rule() не подходит
Если at-rule() не поддерживается браузером или требуется более глубокий анализ, воспользуйтесь приведенными ниже рекомендациями.
Сначала попробуйте свойства, значения или селекторы.
@supports уже может обнаруживать свойства, значения и селекторы (через @supports selector(...)). Во многих случаях вы можете использовать их, чтобы определить, поддерживается ли функция, не проверяя само правило.
Например, вместо @supports at-rule(@function) для обнаружения поддержки пользовательских функций можно использовать @supports (color: --foo()).
В других случаях могут быть псевдоклассы или псевдоэлементы, которые доступны только при поддержке определенного at-правила, которое можно использовать для обнаружения поддержки.
Определение типов запросов контейнера
at-rule() позволяет обнаруживать at-правила только по названию.
Он НЕ позволяет обнаруживать другие синтаксические конструкции или дескрипторы.
Например, следующий вариант работать не будет:
@supports at-rule(@container style(--a: 1)) {
/* ... */
}
Для многих типов запросов контейнера можно использовать container-type с подходящим значением.
Например, @supports (container-type: scroll-state) для запросов состояния прокрутки или @supports (container-type: size)container-type: anchoredforanchored()`.
Однако для запросов стиля container-type не существует.
ВАЖНО! НЕ пытайтесь использовать @supports (container-type: style) для определения поддержки запросов стилей, так как это не сработает.
Вместо этого вы можете попробовать запрос стиля, который всегда верен:
@container style(--a: 1) or (not (style(--a: 1))) {
/* Rules here will only be applied if style queries are supported */
}
Это будет работать в любом браузере, который поддерживает запросы стилей, независимо от того, какое имя или значение свойства вы используете, при условии, что они одинаковы в обоих случаях.
Зарегистрированные пользовательские свойства (@property)
В некоторых случаях, если условный CSS, который нужно применить, можно сократить до одного свойства, вы можете использовать специальное дополнительное свойство, зарегистрированное для этой цели:
/* Use a custom property to conditionally include the dash animation */
@property --progress-dash-animation {
syntax: "*";
inherits: false;
initial-value: , progress-dash 3s ease-in-out infinite;
}
.spinner {
/* The dash animation is only included if @property is supported */
animation:
progress-spin var(--_used-spinner-duration) linear infinite
var(--progress-dash-animation, );
}
Для более общего решения вы можете зарегистрировать ненаследуемое свойство и задать для него значение (пробел) в корневом элементе:
{# Тестовый пример: https://codepen.io/leaverou/pen/KwWzpVr #}
@property --supports-atproperty {
syntax: "*";
inherits: false;
}
:root {
--supports-atproperty: ;
}
body {
/* The background is only applied if @property is supported */
background: var(--supports-atproperty, green);
}
Примечания
- Оба варианта работают, только если пробел является допустимой альтернативой. В остальных случаях вам потребуется использовать JS, как описано ниже.
- Решение общего назначения зависит от ненаследования, поэтому оно не будет работать для объявлений в корневом элементе.
Использование JavaScript в крайнем случае
Чтобы проверить поддержку целых at-правил, проверьте наличие определенных интерфейсов в JavaScript.
Например, если определено globalThis.CSSFunctionRule, то поддерживается @function.
Если вам нужно провести более глубокое тестирование (например, для определенных прелюдий, вложенных правил, дескрипторов), вы можете настроить тест и проверить, как он был проанализирован:
const sheet = new CSSStyleSheet();
sheet.replaceSync(`
@page {
@top-left {
content: "test";
}
}
`);
const SUPPORTS_PAGE_MARGINS = Boolean(sheet.cssRules[0]?.cssRules?.[0]);
ВАЖНО!
- Если вы используете JS для определения поддержки функций CSS, НЕ применяйте стили непосредственно из JS. Вместо этого примените класс к корневому элементу и создайте ответвление в CSS.
- Обратите внимание, что запросы контейнеров анализируются, даже если прелюдия не распознается, и нет способа обнаружить поддержку определенных типов запросов контейнеров из структуры CSSOM.
- НЕ используйте
CSS.registerPropertyдля проверки поддержки@property, так как у него более широкая поддержка.
Резервные стратегии
Если это не входит в ваши цели поддержки, используйте @supports (at-rule()) ТОЛЬКО для обнаружения at-правил, поддержка которых уже, чем у самой функции @supports (at-rule()).
Чтобы условно применять CSS на основе поддержки at-правил, которые поставлялись до этой функции, используйте руководство в разделе выше.
Чтобы определить поддержку @supports at-rule() самой по себе, можно использовать at-правило, которое гарантированно существует во всех браузерах, поддерживающих @supports at-rule(), например @supports at-rule(@media) { ... }.