Usando Modernizr para detectar features de HTML5 e CSS3

Conheça e aprenda a usar Modernizr, biblioteca JavaScript que permite detectar features de HTML5 e CSS3 do navegador e prover soluções, caso necessário.

Modernizr logo símbolo

Os recursos e técnicas que estão surgindo com HTML5 e CSS3 são fenomenais e estão levando a web para um próximo nível. Mas o que fazer se já for preciso usar alguns destes recursos ? Como lidar com browsers que ainda não suportam todas as features de HTML5 + CSS3? A solução tem nome: Modernizr.

Modernizr é uma biblioteca JavaScript que detecta quais features de HTML5 e CSS3 o navegador de quem visita o site suporta. Isso permite aos desenvolvedores testar algumas das novas tecnologias e, em seguida, fornecer fallbacks para navegadores que ainda não as suportam. Isto é chamado de feature detection (detecção de característica) e é muito mais eficiente do que browser sniffing.

O Modernizr é muito útil para detectar suporte a CSS3, mas este artigo focará em HTML5. Mas não é preciso se preocupar, já que os princípios são, essencialmente, os mesmos.

Também é importante ter em mente que o Modernizr não “preenche as lacunas” (polyfill). Ele só detecta quais características são suportadas. Mas é possível usar usar o Modernizr como parte do processo de polyfilling.

Começando a usar o Modernizr

Primeiramente, vamos precisar de um pouco de HTML (HTML5, claro!):

<!DOCTYPE html>
<html class="no-js" lang="en">
    <head>
        <meta charset="utf-8">
        <title>Hello Modernizr</title>
        <script src="modernizr.js"></script>
    </head>
 
    <body>
    </body>
</html>

É possível notar no código acima que o arquivo modernizr.js é necessário. É preciso gerar e baixar o arquivo no site do Modernizr, escolhendo as características que serão precisas serem detectadas. Isso ajuda a ter um arquivo modernizr.js com tamanho adequado às necessidades do projeto, já que não é preciso detectar tudo o que o Modernizr é capaz. Há, também, uma versão “development” no site para começar o desenvolvimento rapidamente. Mas, quando for colocar o site em produção, lembre-se de gerar um arquivo personalizado!

Modernizr: tela de download

Tela de download do Modernizr

Ainda observando o trecho de código acima, veja que na segunda linha há uma classe “no-js” no html. O Modernizr funciona substituindo essa classe pela classe “js”; então, ele adiciona classes para todas as features que o navegador suporta e, também, para os recursos que ele não suporta, pré-fixando estas com “no-”. Por exemplo:

<html class="js no-flexbox canvas canvastext no-webgl no-touch geolocation postmessage no-websqldatabase no-indexeddb hashchange no-history draganddrop no-websockets rgba hsla multiplebgs backgroundsize no-borderimage borderradius boxshadow no-textshadow opacity no-cssanimations no-csscolumns no-cssgradients no-cssreflections csstransforms no-csstransforms3d no-csstransitions fontface generatedcontent video audio localstorage sessionstorage no-webworkers no-applicationcache svg inlinesvg smil svgclippaths">

Detecções explícitas com Modernizr

O Modernizr cria um objeto JavaScript global Modernizr que permite consultar diferentes propriedades desse objeto para realizar a detecção de recursos, chamando Modernizr.<feature>. Por exemplo, para testar o suporte a canvas, o código seria:

<script>
if (Modernizr.canvas)
{
    alert("Seu browser suporta HTML5 canvas!");
}
</script>

Como bons desenvolvedores web que somos, nosso objetivo é escrever JavaScript não obstrusivo e progressivo para que todos possam usar o site, portanto, é preciso tomar alguma ação para o caso da feature não ser suportada:

<script>
if (Modernizr.canvas)
{
    alert("Seu browser suporta HTML5 canvas!");
}
else
{
    alert("Seu browser NÃO suporta canvas...");
}
</script>

Ou, caso se queira testar somente a “negação”:

<script>
if ( ! Modernizr.canvas)
{
    alert("Sem canvas aqui...");
}
</script>

Detecção de recursos e Polyfilling com YepNope

Antes de continuar, caso ainda não saiba o que é “Polyfill”, veja este definição do Paul Irish:

Um shim que imita uma API futura, fornecendo funcionalidades de fallback para navegadores mais antigos.

Para maiores informações, leia (em inglês) o artigo “What is a Polyfill?” de Remy Sharp. Voltando ao artigo…

Nos exemplos JavaScript acima, foi mostrada a maneira mais simples de detectar um recurso de browsers usando o Modernizr. Mas e se você quiser detectar um recurso e usar um polyfill para tornar a performance do navegador melhor? É possível, usando YepNope.

YepNope é um carregador condicional, que significa que ele só irá carregar os scripts que são necessários para o browser. E ele já está incluso no Modernizr! Dessa forma, não é preciso se preocupar com downloads e links para outros arquivos JavaScript. Mas como usar o YepNope junto com o Modernizr?

Utilizando canvas como exemplo novamente, geralmente é preciso uma alternativa (fallback) para os navegadores que não o suportam (por exemplo, IE8). A maneira usual de se fazer isso é um link para um polyfill, tal como o FlashCanvas:

<script src="http://flashcanvas.net/bin/flashcanvas.js"></script>

O problema dessa abordagem é que todos os navegadores irão baixar este script. Isso é desnecessário, pois impacta a performance do site, e deve ser evitado sempre que possível. É possível envolver o elemento script em comentários condicionais, mas, caso seja possível manter os arquivos condicionais fora da marcação, então isso é preferível. Isso é possível de ser feito usando Modernizr.load(). Já que o Modernizr tem o YepNope embutido, é facilmente possível testar um recurso e, em seguida, fornecer um polyfill:

A função .load(), por padrão, não está inclusa no arquivo de desenvolvimento do Modernizr. É preciso incluí-la ao gerar o arquivo de download apropriado, conforme mostrado no início do artigo.

O uso básico da função .load() permite que testar a presença de uma feature. Veja este exemplo em que o Modernizr testa o suporte para canvas e, caso o browser não a suporte, ele carrega o FlashCanvas:

Modernizr.load({
    test: Modernizr.canvas,
    nope: 'http://flashcanvas.net/bin/flashcanvas.js'
});

Usando as developer tools do IE8, na aba “Network” é possível ver o download e inicialização do flashcanvas.js. Legal, hã? ;-)

Modernizr + YepNope: checando downloads condicionais no IE8

Modernizr + YepNope: checando downloads condicionais no IE8

Vamos a um exemplo mais prático que detecta o suporte a <input type="date">. Se não for suportado, haverá o carregamento de 2 arquivos jQuery e um arquivo CSS para gerar um seletor de datas:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script src="modernizr.js"></script>
<script>Modernizr.load({
    test: Modernizr.inputtypes.date,
    nope: [
        'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js',
        'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js',
        'jquery-ui.css'
    ],
    complete: function() {
        $('input[type=date]').datepicker({
            dateFormat: 'yy-mm-dd'
        });
    }
});
</script>

Na maioria dos navegadores, o jQuery será carregado, mas, no Opera, não haverá essa necessidade, já que ele já possui um seletor de datas nativo por já suportar <input type="date">.

Seletor de datas no Firefox

Seletor de datas no Opera

E, como você já deve ter imaginado, carregar ou não 2 arquivos JavaScript e uma folha de estilos gera uma grande diferença na performance do site.

Comparação de recursos ao carregar datapicker: Firefox x Opera

Comparação de recursos ao carregar datapicker: Firefox x Opera

Observe como os 2 arquivos jQuery são carregados duas vezes. Isso acontece, mesmo, no YepNope: primeiro ele carrega o recurso e, em seguida, executa-o. Então, não se preocupe, pois isso é normal. E veja, também, todas as propriedades do objeto de teste do YepNope, conhecê-las pode ser bastante útil!

Conclusão

Como pôde ser visto, Modernizr é uma poderosa biblioteca de detecção de features. Ela permite verificar se o navegador suporta vários recursos e, dependendo do resultado, permite que sejam usados polyfills. Este artigo analisou como gerar um arquivo Modernizr e suas 2 maneiras de uso: usando diretamente o objeto Modernizr (Modernizr.<feature>) e, em seguida, usando YepNope.

Com isso, damos mais um passo rumo ao desenvolvimento de uma web melhor, mais profissional e com desenvolvedores mais conscientes das limitações intrínsecas aos diversos dispositivos que podem ser usados para se acessar um site. Sabíamos do “mal”, agora conhecemos a cura.