Carregando...

Feature queries CSS

As container queries perguntam a largura de um pai. As media queries olham para o viewport. As feature queries fazem outra pergunta: este browser entende este CSS? Com @supports, entregas uma base sólida e só desbloqueias layout ou seletores modernos onde eles funcionam.

Melhoria progressiva, não um jogo de sorte

Uma feature query é um portão de capacidade. Não apagas os estilos antigos — manténs um layout que funciona em todo o lado e, dentro de @supports, acrescentas uma camada mais rica quando o motor consegue fazer parse da funcionalidade (por exemplo display: grid ou gap em flex).

Forma básica de @supports

A forma habitual testa um par propriedade–valor. Se o browser trata essa declaração, as regras aninhadas aplicam-se:

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;
}
}

Fora do bloco, os cartões empilham com uma margem simples. Dentro de @supports (display: grid), a mesma lista vira uma grelha responsiva — motores antigos mantêm a pilha; os modernos recebem a grelha.

Combinar condições: and, or, not

Podes exigir várias funcionalidades, aceitar alternativas ou inverter um teste:

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 aperta o portão (os dois têm de passar). or alarga-o. not estiliza o caminho sem suporte — útil para um fallback deliberado, desde que esse fallback fique legível e completo.

Testar seletores com selector()

Algumas funcionalidades são seletores, não propriedades. Envolve-as em selector() para a query perguntar: «consegues fazer parse deste seletor?»

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;
}
}

Sem selector(), um :has() nu dentro de @supports não é o padrão fiável. Com ele, browsers sem :has() simplesmente saltam as regras enriquecidas e mantêm os estilos de link da base.

Quem faz que pergunta?

📊 Media, container, and feature queries

Pergunta que estás a fazer Preferir Ferramenta típica
Qual a largura do viewport / contexto do dispositivo? Cascão da página, breakpoints @media (…)
Qual a largura deste pai à volta do componente? Cartões em slots desiguais @container (…) depois de container-type
O browser suporta este CSS? Melhoria progressiva @supports (…) / selector(…)

Estas ferramentas encaixam bem: media para a página, container para o slot, @supports para capacidade. Não uses @supports para fingir um breakpoint, nem @media para fingir um teste de funcionalidade.

Base primeiro, enriquecimento depois

Um padrão prático mantém o aspeto partilhado fora do portão e melhora o layout dentro:

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;
}
}

Todo o browser recebe padding, tipografia e links clicáveis. Flex + gap só aparecem quando ambos são entendidos — sem buraco vazio se um faltar.

Nesting e @supports juntos

As peças do Modern Toolkit combinam-se. O nesting organiza seletores; @supports continua a ser o portão de capacidade:

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;
}
}
}

Se o próprio nesting não for suportado, mantém um equivalente plano fora ou aceita que a forma aninhada faz parte do caminho enriquecido — a mesma mentalidade de melhoria progressiva.

Experimenta tu

  1. Estiliza uma lista como pilha vertical simples e envolve um layout Grid em @supports (display: grid).
  2. Exige gap com and para o espaçamento flex/grid não aplicar a meio.
  3. Acrescenta @supports not (display: grid) com um fallback max-width claro — os dois caminhos devem parecer intencionais.
  4. Bloqueia uma regra :has() com @supports selector(:has(*)).
  5. Resiste a meter todo o visual dentro de @supports; deixa cor de marca e tipografia na base.

Erros comuns

  • Meter o único layout utilizável dentro de @supports sem base — browsers sem suporte veem a página partida
  • Escrever @supports (display) sem valor — feature queries precisam de um par propriedade–valor (ou selector(…))
  • Usar @supports onde cabe @media (ou o inverso) — capacidade ≠ largura do viewport
  • Testar uma propriedade que a base já exige — só bloqueia o enriquecimento
  • Pilhas profundas de @supports aninhados por ganhos pequenos — prefere uma camada enriquecida clara

Resumo

  • @supports condiciona CSS à capacidade do browser (feature queries)
  • Testa com (property: value), combina com and / or / not e usa selector() para seletores
  • Mantém uma base sólida; enriquece quando há suporte
  • Lembra o trio: @media → viewport, @container → tamanho do pai, @supports → capacidade
  • O Modern Toolkit termina aqui — módulo seguinte: Acessibilidade e fecho (accessibility)

🧠 Teste Seu Conhecimento

Pronto para Começar

Teste Seu Conhecimento

Desafie-se com este questionário interativo e veja o quão bem você entende o tópico

❓
6
Perguntas
🎯
70%
Para Passar
♾️
∞
Tempo
🔄
∞
Tentativas

📝 Instruções

  • Leia cada pergunta cuidadosamente
  • Selecione a melhor resposta para cada pergunta
  • Você pode refazer o quiz quantas vezes quiser
  • Seu progresso será mostrado no topo