Загрузка...

Feature queries в CSS

Container queries спрашивают, какова ширина родителя. Media queries смотрят на viewport. Feature queries задают совсем другой вопрос: понимает ли этот браузер данный CSS? С @supports вы отдаёте надёжную базу, а современную вёрстку или селекторы включаете только там, где движок с ними справляется.

Прогрессивное улучшение, а не ставка

Feature query — это шлюз по возможностям. Старые стили не выкидывают: оставляют раскладку, которая работает везде, а более богатый слой добавляют внутри @supports, когда движок умеет разобрать нужную возможность (например display: grid или gap во flex).

Базовый @supports

Обычная форма проверяет пару свойство–значение. Если браузер понимает это объявление, вложенные правила применяются:

Unlock Grid only when Grid is understood

css
.card-list {
display: block;
}

.card-list .card {
margin-bottom: 1rem;
padding: 1rem;
border: 1px solid #e2e8f0;
border-radius: 0.75rem;
background: #fff;
}

@supports (display: grid) {
.card-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
gap: 1rem;
}

.card-list .card {
margin-bottom: 0;
}
}

Снаружи блока карточки складываются в столбец с простым отступом. Внутри @supports (display: grid) тот же список становится адаптивной сеткой — старые движки сохраняют столбец, современные получают grid.

Комбинация условий: and, or, not

Можно требовать несколько возможностей сразу, принимать альтернативы или инвертировать проверку:

and, or, and not in feature queries

css
@supports (display: grid) and (gap: 1rem) {
.toolbar {
display: grid;
grid-auto-flow: column;
gap: 0.75rem;
align-items: center;
}
}

@supports (display: flex) or (display: grid) {
.cluster {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
}

@supports not (display: grid) {
.card-list .card {
max-width: 36rem;
}
}

and сужает шлюз (должны пройти оба условия). or расширяет его. not стилизует путь без поддержки — удобно для осознанного fallback, если этот fallback действительно читаемый и полный.

Селекторы через selector()

Некоторые возможности — селекторы, а не свойства. Оберните их в selector(), чтобы запрос спрашивал: «умеешь ли разобрать этот селектор?»

Gate styles that need :has()

css
.nav a {
color: #0f172a;
text-decoration: none;
}

@supports selector(:has(*)) {
.nav:has(a:focus-visible) {
outline: 2px solid #2563eb;
outline-offset: 4px;
}

.card:has(img) .title {
font-weight: 700;
}
}

Без selector() голый :has() внутри @supports — ненадёжный приём. С ним браузеры без :has() просто пропускают улучшенные правила и оставляют базовые стили ссылок.

Кто какой вопрос задаёт?

📊 Media, container, and feature queries

Ваш вопрос Когда уместно Типичный инструмент
Насколько широк viewport / контекст устройства? Оболочка страницы, брейкпоинты @media (…)
Насколько широк этот родитель вокруг компонента? Карточки в неравных слотах @container (…) после container-type
Поддерживает ли браузер этот CSS? Прогрессивное улучшение @supports (…) / selector(…)

Эти инструменты хорошо складываются: media для страницы, container для слота, @supports для возможностей. Не подменяйте брейкпоинт через @supports и не имитируйте проверку возможности через @media.

Сначала база, потом улучшение

Практичный приём: общий вид держать снаружи шлюза, а усиленную раскладку — внутри:

Shared skin outside; enhanced layout inside

css
.feature-panel {
padding: 1.25rem;
border-radius: 0.75rem;
background: #f8fafc;
color: #0f172a;
}

.feature-panel .lead {
margin: 0 0 0.75rem;
font-size: 1.125rem;
line-height: 1.5;
}

.feature-panel .actions {
display: block;
}

.feature-panel .actions a {
display: inline-block;
margin: 0.25rem 0.5rem 0.25rem 0;
padding: 0.5rem 0.875rem;
border-radius: 0.5rem;
background: #e2e8f0;
color: inherit;
text-decoration: none;
}

@supports (display: flex) and (gap: 0.5rem) {
.feature-panel .actions {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}

.feature-panel .actions a {
margin: 0;
}
}

Каждый браузер получает отступы, типографику и кликабельные ссылки. Flex и gap появляются только когда понятны оба — без «дыры», если чего-то не хватает.

Nesting вместе с @supports

Части Modern Toolkit сочетаются. Nesting упорядочивает селекторы; шлюз возможностей по-прежнему у @supports:

Nesting inside a support block

css
.pricing {
padding: 1rem;
border: 1px solid #e2e8f0;
}

@supports (display: grid) {
.pricing {
display: grid;
gap: 1rem;

& .tier {
padding: 1rem;
background: #fff;
}

& .tier .price {
font-size: 1.5rem;
font-weight: 700;
}
}
}

Если сам nesting не поддерживается, держите плоский эквивалент снаружи или считайте вложенную форму частью улучшенного пути — та же логика прогрессивного улучшения.

Попробуйте сами

  1. Стилизуйте список как простой вертикальный столбец, затем оберните Grid-раскладку в @supports (display: grid).
  2. Потребуйте gap через and, чтобы отступы flex/grid не применялись наполовину.
  3. Добавьте @supports not (display: grid) с явным max-width — оба пути должны выглядеть намеренно.
  4. Закройте правило с :has() через @supports selector(:has(*)).
  5. Не переносите весь визуал внутрь @supports; цвет бренда и типографику оставьте в базе.

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

  • Класть единственную рабочую раскладку внутрь @supports без базы — браузеры без поддержки получают сломанную страницу
  • Писать @supports (display) без значения — feature query нуждается в паре свойство–значение (или в selector(…))
  • Ставить @supports там, где нужен @media (или наоборот) — возможность ≠ ширина viewport
  • Проверять свойство, без которого база уже не живёт — шлюзуйте только улучшение
  • Глубокие стопки вложенных @supports ради мелких выигрышей — лучше один ясный улучшенный слой

Кратко

  • @supports включает CSS по возможностям браузера (feature queries)
  • Проверяйте (property: value), комбинируйте через and / or / not, для селекторов используйте selector()
  • Держите крепкую базу; улучшайте, когда поддержка есть
  • Тройка: @media → viewport, @container → размер родителя, @supports → возможности
  • Modern Toolkit здесь заканчивается — следующий модуль: Accessibility & Wrap-up (accessibility)

🧠 Проверьте Свои Знания

Готов к Началу

Проверьте Свои Знания

Бросьте себе вызов с помощью этой интерактивной викторины и узнайте, насколько хорошо вы понимаете тему

❓
6
Вопросы
🎯
70%
Для Прохождения
♾️
∞
Время
🔄
∞
Попытки

📝 Инструкции

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