@supports: feature queries

@supports — CSS-правило для условного применения стилей в зависимости от поддержки браузером конкретного CSS-свойства или значения.

Зачем нужно

@supports позволяет писать прогрессивно улучшающийся CSS: базовые стили для всех браузеров, расширенные — только там где поддерживается современная фича. Это альтернатива JavaScript-полифиллам для чисто визуальных возможностей. Особенно полезен при постепенном внедрении Grid, container queries, color-mix и других новых CSS-возможностей.

Где используется

  • Прогрессивное улучшение с Grid/Flexbox
  • Условное применение container queries
  • Использование :has только при поддержке
  • Проверка поддержки display: grid vs fallback float/flex
  • Кастомные свойства и color-mix

Основной контент

Базовый синтаксис

/* Применить только если браузер поддерживает display: grid */
@supports (display: grid) {
  .layout {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
  }
}

/* Fallback для старых браузеров */
.layout {
  display: flex;
  flex-wrap: wrap;
}

@supports (display: grid) {
  .layout {
    display: grid;
  }
}

Логические операторы

/* not — если НЕ поддерживается */
@supports not (display: grid) {
  .layout {
    float: left;
    width: 33.33%;
  }
}

/* and — все условия */
@supports (display: grid) and (gap: 1px) {
  .grid { display: grid; gap: 16px; }
}

/* or — любое из условий */
@supports (transform-origin: 5px 5px 5px) or
          (-webkit-transform-origin: 5px 5px 5px) {
  .rotated { transform-origin: center; }
}

Проверка selector

/* Проверить поддержку :has */
@supports selector(:has(*)) {
  .card:has(img) {
    display: grid;
    grid-template-columns: 1fr 2fr;
  }
}

/* Проверить поддержку :is */
@supports selector(:is(a, b)) {
  :is(h1, h2, h3) { font-family: serif; }
}

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

/* Container queries — прогрессивно */
.component {
  /* Базовый layout */
  display: flex;
  flex-direction: column;
}

@supports (container-type: inline-size) {
  .wrapper {
    container-type: inline-size;
  }

  @container (min-width: 400px) {
    .component {
      flex-direction: row;
    }
  }
}

/* oklch — прогрессивный цвет */
:root {
  --accent: #0070f3;
}

@supports (color: oklch(0.7 0.2 130)) {
  :root {
    --accent: oklch(0.55 0.22 260);
  }
}

В JavaScript

// CSS.supports — то же самое в JS
if (CSS.supports('display', 'grid')) {
  console.log('Grid supported');
}

if (CSS.supports('(display: grid) and (gap: 1px)')) {
  // комплексная проверка
}

Частые ошибки

  • @supports не защищает от синтаксических ошибок — если свойство поддерживается но значение некорректно, браузер всё равно применит блок
  • Проверка display: flex всегда true — все современные браузеры поддерживают flex; проверять нет смысла
  • not без скобок@supports not display: grid — синтаксическая ошибка; нужно @supports not (display: grid)
  • Порядок имеет значение — правила каскадируются; @supports-блок не поднимает специфичность

Связанные темы

Ресурсы