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 já? 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.
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!):
1 2 3 4 5 6 7 8 9 10 11 |
<!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!
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:
1 |
<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:
1 2 3 4 5 6 |
<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:
1 2 3 4 5 6 7 8 9 10 |
<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”:
1 2 3 4 5 6 |
<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:
1 |
<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:
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:
1 2 3 4 |
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ã? ;-)
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">
.
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.
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.