Categorias
Projetos

CSS @supports (CSS Feature Queries): detecção nativa de suporte a propriedades CSS

A detecção de recursos via JavaScript é uma prática recomendada no lado do cliente, mas, infelizmente, essa mesma funcionalidade não está disponível em CSS. O que dá para fazer é repetir as mesmas propriedades várias vezes com cada prefixo de navegador. Que nojo… Mas eis que (finalmente) surge uma solução: CSS @supports!

Firefox, Chrome e Opera recentemente adicionaram suporte para CSS @supports (CSS) e CSS.supports (JavaScript) para detectar o suporte de navegador para uma determinada propriedade de estilo. Vejamos como isso funciona.

CSS @supports

A diretiva @supports de CSS funciona mais ou menos da mesma maneira que media queries:

@supports (propriedade: valor) {
/* regras */
}

CSS @supports permite aos desenvolvedores verificarmos o suporte a estilo de várias maneiras diferentes.

Checagem de propriedades básicas

É possível checar propriedades básicas de CSS como no exemplo:

@supports (display: flex) {
div {
display: flex;
}
}

Esse é o uso mais básico possível do @supports.

Palavra-chave not

Tal como em media queries, CSS @supports pode usar a palavra-chave **not** para checar um não-suporte:

@supports not (display: flex) {
/* Estilos alternativos */
div {
float: left;
}
}

Checagem múltipla e condicionais

Se for preciso checar múltiplas propriedades CSS, isso pode ser feito ao usar as palavras-chave and ou or encadeadas:

/* or */
@supports (display: -webkit-flex) or
(display: -moz-flex) or
(display: flex) {
/* Regras CSS */
}
/* and */
@supports (display: flex) and (-webkit-appearance: caret) {
/* Algo muito louco aqui */
}

Assim como em linguagens de programação, é possível encadear múltiplas condições com parênteses:

/* and e or */
@supports ( (display: -webkit-flex) or (display: -moz-flex) or (display: flex) ) and
(-webkit-appearance: caret) {
/* Estilos aqui */
}

Como dito, o padrão condicional da estrutura de @supports coincide com o padrão condicional de @media.

JavaScript CSS.supports

A contrapartida JavaScript para CSS @supports é window.CSS.supports. A especificação CSS.supports fornece 2 métodos de uso.

O primeiro inclui fornecer 2 argumentos, um para a propriedade e outro para o valor:

var supportsFlex = CSS.supports( 'display', 'flex' );

O segundo método de uso inclui simplesmente fornecer a seqüência inteira a ser analisada:

var supportsFlexAndAppearance = CSS.supports( '(display: flex) and (-webkit-appearance: caret)' );

É muito bom que haja opções e seja possível verificar o suporte de CSS através de qualquer método — isso evita a verificação de propriedade em nós transitórios e construção de seqüências de caracteres para verificar o suporte.

Antes de usar o método JavaScript de CSS suporte, é importante detectar o recurso primeiro — o Opera usa um nome de método diferente, então é preciso ficar atento:

var supportsCSS = !!( (window.CSS && window.CSS.supports) || window.supportsCSS || false );

Uso de @supports

Na maioria dos casos, a melhor maneira de usar @supports é configurando um conjunto mais antigo de estilos como backup e, em seguida, “cancelando” esses estilos e aprimorando se uma determinada propriedade é suportada — Progressive Enhancement, baby!

Um caso de uso brilhante para @supports é em layouts. Veja um exemplo envolvendo Flexbox:

section {
float: left;
}
@supports (display: -webkit-flex) or
(display: -moz-flex) or
(display: flex) {
section {
display: -webkit-flex;
display: -moz-flex;
display: flex;
float: none;
}
}

Exemplo prático: usando flow-root

Atualmente (na data de publicação deste artigo) o suporte para flow-root é quase nulo, conseguindo somente seus modestos 0,2% — se não souber do que se trata, leia um artigo a respeito.

Mas, graças a @supports, é possível usar o novo valor da propriedade CSS display e se livrar de uma vez por todas do famoso hack clearfix. E de uma maneira simplíssima:

.left,
.right {
width: 50%;
}
.left {
float: left;
margin-bottom: 2em;
}
.right {
float: right;
}
.wrapper::after {
content: '';
display: block;
clear: both;
}
@supports (display: flow-root) {
.wrapper {
display: flow-root;
}
/* IE 11 */
.wrapper::after {
content: none;
}
}

Ou seja, tal como de costume em projetos que seguem a filosofia progressive enhancement, especifica-se um valor que se tem certeza que funciona amplamente e, logo em seguida, valendo-se dos efeitos de cascata das folhas de estilo, verifica-se o suporte a flow-root com @supports para escrever a regra usando as novas capacidades de CSS.

Conclusão sobre @supports

Na verdade, @supports não é nenhuma grande novidade no mundo CSS, mas, infelizmente, ainda não é muito usado para verificações de suporte e desenvolvimento progressive enhancement.

Na data de publicação deste artigo, é possível ver que o suporte global de navegadores para @supports já é excelente, ultrapassando a casa dos 92%:

@supports revela-se como uma diretiva importante de verificação de estilos, indispensável quando o projeto web segue progressive enhancement. De escrita simples e rápida, @supports deveria estar muito, muito mais presente nas linhas de código CSS do que é possível encontrar atualmente.