CSS agora consegue perguntar se uma at-rule existe: conheça o at-rule() do Firefox 157

O CSS já consegue perguntar se o navegador entende uma propriedade, um valor, um seletor ou determinada tecnologia de fonte. Faltava uma resposta direta para algo mais básico: este navegador reconhece uma at-rule como @scope, @layer ou @container?

O Firefox 157, lançado em 29 de setembro, adiciona suporte à função at-rule() dentro de @supports. Com ela, a consulta deixa de procurar uma propriedade que sirva como representante indireta e passa a verificar a própria regra. A sintaxe vem do rascunho de nível 5 do módulo CSS Conditional Rules.

@supports at-rule(@scope) {
  @scope (.article) to (.comments) {
    a {
      color: var(--link-color);
    }
  }
}

Por que testar uma propriedade nem sempre respondia à pergunta certa

Uma consulta tradicional usa uma declaração entre parênteses. O navegador retorna verdadeiro quando aceita aquela combinação de propriedade e valor.

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

Para seletores, existe selector(). Para tecnologias e formatos de fonte, existem font-tech() e font-format(). Uma at-rule não cabe bem nesses testes porque seu suporte envolve a regra, o contexto em que ela pode aparecer, seus descritores e a forma como o bloco interno é processado.

Antes de at-rule(), era comum testar uma propriedade associada ao recurso. Isso podia funcionar como aproximação, mas não era uma equivalência. Uma implementação pode reconhecer uma propriedade sem aceitar a at-rule que normalmente a organiza, ou aceitar a estrutura principal e ainda ter suporte parcial a detalhes internos. A consulta respondia “esta declaração é válida”, enquanto o código queria saber “posso usar esta regra?”.

O teste verifica reconhecimento, não qualidade da implementação

Segundo a especificação, at-rule(@nome) retorna verdadeiro quando o navegador aceita uma at-rule iniciada por aquele nome em algum contexto. Essa definição é útil, mas não funciona como uma suíte de compatibilidade. Ela não confirma que cada descritor, combinação ou comportamento da regra foi implementado exatamente como a aplicação espera.

Um resultado positivo para @container, por exemplo, informa que a at-rule é reconhecida. Se o projeto depende de uma consulta de scroll state ou de uma sintaxe mais recente dentro dela, o teste precisa ser mais específico. Quando existir uma propriedade, seletor ou valor indispensável ao caso de uso, as condições podem ser combinadas.

@supports at-rule(@container) and (container-type: inline-size) {
  .card-list {
    container-type: inline-size;
  }

  @container (width > 42rem) {
    .card-list {
      grid-template-columns: repeat(3, 1fr);
    }
  }
}

A mesma cautela vale para recursos que ainda estão em desenvolvimento. at-rule() faz parte de um Working Draft do CSS Conditional Level 5. O Firefox 157 não transforma todas as ideias do nível 5 em recursos prontos, nem um teste verdadeiro para uma regra torna toda a especificação estável.

O fallback mais seguro continua começando fora da consulta

O suporte a at-rule() ainda não é uniforme. Chromium já implementa a função e o Firefox entra agora, enquanto versões estáveis do Safari ainda podem não reconhecê-la. A estratégia mais previsível é escrever primeiro uma apresentação funcional com CSS conhecido e colocar a melhoria dentro de uma consulta positiva.

.article a {
  color: #075985;
}

@supports at-rule(@scope) {
  @scope (.article) to (.comments) {
    a {
      color: var(--link-color);
    }
  }
}

Um navegador sem a nova função mantém a regra inicial. Um navegador que entende o teste e também reconhece @scope entra no bloco aprimorado. Isso aproveita o mecanismo normal da cascata e evita depender de detecção por nome de navegador ou versão.

Consultas negativas com not existem, mas costumam deixar o fallback mais difícil de raciocinar quando a própria sintaxe da consulta é nova. Para melhorias progressivas, declarar a base fora do @supports e condicionar apenas o recurso novo mantém a leitura mais direta.

A função também pode controlar um @import

O Firefox 157 também aceita o teste dentro de supports() em uma regra @import. Isso permite carregar uma folha separada somente quando a at-rule necessária estiver disponível.

@import url("scoped-components.css") supports(at-rule(@scope));

Essa forma pode ser útil para isolar uma camada de aprimoramento, mas não deve virar desculpa para fragmentar todo o CSS por recurso. Ela também precisa aparecer no lugar válido para @import, antes das regras de estilo comuns da folha. Na maior parte dos componentes, manter o bloco condicional perto do fallback continua facilitando a manutenção.

Feature detection é melhor do que tentar adivinhar o navegador

A chegada ao Firefox deixa at-rule() mais útil em projetos reais, mas o ganho principal é conceitual. O código pode declarar a capacidade de que precisa em vez de manter uma lista de versões presumidamente compatíveis. Isso resiste melhor a atualizações, flags experimentais, navegadores baseados no mesmo motor e implementações que chegam em calendários diferentes.

Também vale lembrar que nem todo CSS novo precisa de uma consulta. A linguagem já ignora declarações e regras que não reconhece, e muitas melhorias podem ser aplicadas pela cascata sem um bloco extra. @supports se paga quando a ativação parcial deixaria a interface inconsistente, quando várias mudanças precisam entrar juntas ou quando a versão nova exige neutralizar parte do fallback.

O at-rule() não muda essa lógica. Ele apenas fecha uma lacuna: quando a decisão realmente depende do suporte a uma at-rule, o CSS finalmente consegue fazer a pergunta certa.

Fontes