Nenhum navegador deixado para trás: Estraté

De Brandon Satrom

Nenhum navegador deixado para trás: Estratégia de adoção do HTML5

Há muitas razões para se entusiasmar com o HTML5. Com uma nova marcação (markup) e novos recursos CSS e APIs JavaScript, o escopo de possibilidades na Web está crescendo a uma velocidade incrível. E com a concorrência acirrada dos fabricantes de navegadores, a lista de recursos aumenta quase diariamente. Entre compilações noturnas, lançamentos no canal de desenvolvimento e pré-visualizações regulares das plataformas, os navegadores estão mudando rapidamente e os desenvolvedores Web estão embarcando nessa jornada estimulante.

Mas por mais que as comunidades de desenvolvimento e navegadores estimulem o sucesso do HTML5, a grande maioria dos usuários da Web ainda não adotou os novos navegadores e versões que nós estamos usando. Se você trabalha como desenvolvedor Web em um ambiente grande de desenvolvimento ou uma empresa com uma base grande de usuários, provavelmente já sabia disso. Mesmo que trabalhe em um ambiente ou empreendimento pequeno que fornece alguns serviços pela Web, você provavelmente passa bastante tempo tentando garantir que seu site atenda ao maior número possível de navegadores e versões de navegador.

Dada essa realidade, não temos que imaginar se o HTML5 está pronto para ser usado, mas sim se você está pronto para ele. Por exemplo, vamos supor que você criou uma página com algumas das novas marcas semânticas (como <header> e <article>), adicionou alguns recursos CSS novos (como o border-radius e o box-shadow) e até incluiu um elemento <canvas> para desenhar um logotipo do HTML5 na página.

Nos navegadores mais novos, como o Internet Explorer 9, o Firefox 4 e superiores ou o Google Chrome, o resultado da renderização será o da Figura 1. Mas se tentar carregar no Internet Explorer 8 ou um navegador anterior, você verá algo mais parecido à Figura 2: uma página completamente quebrada.

Figura 1 Página semântica com estilos e um elemento <canvas> do HTML5 renderizada no Internet Explorer 9

Figura 2 A mesma página semântica renderizada no Internet Explorer 8 sem estilos e sem <canvas>

Eu não o culparia se, depois de analisar todos os recursos maravilhosos do HTML5 e passar por uma experiência como essa, você decidisse que seria melhor esperar. É fácil concluir que, pronto ou não, o HTML5 ainda não é a melhor opção para você e seus usuários.

Mas antes de marcar uma data em 2022 para dar uma nova olhada no HTML5, leia o restante deste artigo. Meu objetivo este mês é ensinar estratégias práticas para que você possa adotar as tecnologias HTML5 hoje sem causar uma degradação perceptível como a da Figura 2. Neste artigo, vou discutir os seguintes itens:

  1. Detecção de recursos versus detecção de UA (user agent - agente do usuário)
  2. Polyfilling com JavaScript
  3. Degradação imperceptível de recursos

Esses três tópicos vão mostrar boa parte do que vocês precisam saber para construir sites para uma ampla variedade de navegadores. Quando terminarmos, vocês terão uma estratégia sólida para adotar as tecnologias HTML5 com confiança e sem adiamentos. Além disso, terão ferramentas para aprimorar progressivamente os sites para os navegadores mais novos e reduzir recursos ou capacidades de forma imperceptível para outros.

A importância da detecção de recursos

Para proporcionar experiências estáveis e consistentes, o desenvolvedor precisa de algumas informações sobre o navegador do usuário. Antes era comum determinar tais informações com JavaScripts como este:

var userAgent = navigator.userAgent;



if (userAgent.indexOf('MSIE') >= 0) {

  console.log("Hello, IE user");

} else if (userAgent.indexOf('Firefox') >= 0) {

  console.log("Hello, Firefox user");

} else if (userAgent.indexOf('Chrome') >= 0) {

  console.log("Hello, Chrome user");

}

Essa técnica, conhecida como detecção de UA, é muito usada para determinar qual navegador está solicitando sua página. A lógica é que conhecendo o navegador do usuário (Internet Explorer 7, por exemplo), você pode decidir no tempo de execução quais recursos do site devem ser ativados ou desativados. A detecção de UA equivale a dizer ao navegador: "Quem é você?" (Para uma análise aprofundada da detecção de UA e outras técnicas semelhantes, acesse bit.ly/mlgHHY.)

O problema desse método é que o navegador pode mentir. A cadeia de caracteres de UA é uma informação configurável pelo usuário que não fornece uma descrição 100 por cento precisa do navegador em questão. E como a adoção dessa técnica se expandiu, muitos fabricantes começaram a adicionar conteúdos extras às próprias cadeias de caracteres de UA para fazer o script traçar suposições incorretas a respeito do navegador usado, desviando assim da detecção. Alguns navegadores até incluem um recurso que permite ao usuário mudar a cadeia de caracteres de UA com apenas alguns cliques.

Mas o objetivo da detecção de UA nunca foi descobrir o navegador e a versão do usuário. E certamente não era fornecer um pretexto para mandar os usuários fazerem download de outro navegador, caso usassem um que você não aprovava — embora alguns usem essa técnica. O usuário pode escolher o navegador que vai usar. A nossa responsabilidade como desenvolvedores é proporcionar a experiência mais confiável e consistente possível, e não impor uma preferência. O propósito da detecção de UA sempre foi fornecer a você uma visão precisa dos recursos que podem ser potencializados dentro do navegador atual do usuário. O conhecimento do navegador propriamente dito é apenas um meio para esse fim.

Hoje existem alternativas à detecção de UA, e uma que está se tornando cada vez mais popular — graças, em parte, ao jQuery e ao Modernizr — é a detecção de objetos ou recursos. Os termos têm o mesmo significado, mas neste artigo vou usar apenas "detecção de recursos".

O objetivo dessa detecção é verificar se determinado recurso é suportado pelo navegador atual do usuário. Se a detecção de UA equivale a perguntar "quem é você", a detecção de recursos é como perguntar ao navegador "do que você é capaz" — uma pergunta muito mais direta e uma forma mais confiável de fornecer funcionalidades condicionais aos usuários. A implementação correta dos scripts de detecção dificulta muito a falsificação e a comunicação errônea dos recursos suportados.

Detecção de recursos manual

Então como é a detecção de recursos, comparada ao exemplo da detecção de UA? Para responder essa pergunta, vamos corrigir os problemas que apareceram quando visualizamos a página de HTML5 (mostrada na Figura 1) no Internet Explorer 8 em vez do Internet Explorer 9. A marcação (markup) dessa página está listada na Figura 3.

Figure 3 Página com nova marcação (markup) semântica de HTML5

<!DOCTYPE html>

<html lang="en">

<head>

  <meta charset="utf-8" />

  <title>My Awesome Site</title>

  <style>

    body { font-size: 16px; font-family: arial,helvetica,clean,sans-serif;  }

    header h1 { font-size: 36px; margin-bottom: 25px; }

    article 

    {

      background: lightblue;

      margin-bottom: 10px;

      padding: 5px;

      border-radius: 10px;

      box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.5);

    }

    article h1 { font-size: 12px; }

  </style>

</head>

<body>

  <header><h1>My Awesome Site</h1></header>

  <article>

    <header><h1>An Article</h1></header>

    <p>Isn't this awesome?</p>

  </article>

  <canvas width="250" height="500"></canvas>

</body>

<script src="../js/html5CanvasLogo.js" type="text/javascript"></script> 

</html>

As diferenças entre o Internet Explorer 9 e o Internet Explorer 8, como mostram as Figuras 1 e 2, são drásticas. Para começar, a página está completamente sem estilo, como se o CSS não existisse. E sinto falta do belo escudo do HTML5 no final da página. Esses problemas podem ser corrigidos facilmente, e a detecção de recursos é o primeiro passo para identificá-los.

A causa de ambos é simples: <header>, <article> e <canvas> não são elementos de HTML válidos para o Internet Explorer 8, portanto não posso trabalhar com eles. Para resolver a questão do <canvas>, em vez de usar a detecção de UA para determinar qual navegador e versão estão sendo usados, quero perguntar ao navegador, via JavaScript, se ele tem suporte para o elemento <canvas> e suas APIs JavaScript. A verificação dos recursos do canvas fica assim:

!!document.createElement('canvas').getContext

Essa instrução gera alguns resultados. Primeiro, ela usa a negação dupla (!!) para forçar os valores indefinidos a serem explicitamente falsos. Depois cria manualmente um novo elemento canvas e o anexa ao DOM. Finalmente, chama o getContext, uma nova função disponível para elementos canvas que serve para manipular a API do Canvas via JavaScript. Se eu estiver usando o Internet Explorer 9, o retorno da instrução será "verdadeiro". No Internet Explorer 8, o retorno será "indefinido" e a negação dupla o forçará a ser falso.

Esse é o aspecto mais básico da detecção de recursos. Essa e outras instruções similares proporcionam uma forma mais confiável de consultar os recursos suportados pelo navegador. Para mais informações sobre a detecção de recursos manual, visite bit.ly/9kNDAO.

Usando o Modernizr para detectar recursos

Embora tenha aprimorado a detecção de UA, a detecção manual de recursos ainda deixa para você o trabalho pesado de detectar a disponibilidade do recurso e decidir o que fazer se ele não existir. O exemplo do canvas era simples e exigia apenas uma linha de código, mas não é assim com todos os recursos que queremos detectar — tampouco o código da detecção é o mesmo para todos os navegadores. Detectar o suporte aos módulos CSS3 que usei anteriormente (border-radius e box-shadow), por exemplo, pode ser um pouco mais complicado.

Felizmente, o Modernizr (modernizr.com) oferece um método mais eficaz. Modernizr é uma biblioteca JavaScript que "… detecta a disponibilidade de implementações nativas das tecnologias Web de última geração, ou seja, recursos derivados das especificações HTML5 e CSS3". A adição de uma referência ao Modernizr em suas páginas gera quatro resultados:

  1. Uma lista abrangente dos recursos suportados, que é adicionada à sua marcação (markup) para habilitar as definições CSS condicionais.
  2. Um objeto JavaScript, que auxilia na detecção de recursos baseada em script.
  3. Todas as novas marcas HTML5 adicionadas ao DOM no tempo de execução, em benefício do Internet Explorer 8 e dos navegadores anteriores (vamos falar mais sobre isso).
  4. Um carregador de scripts para carregar polyfills condicionalmente às suas páginas.

Não vamos discutir o primeiro item neste artigo, mas vocês podem acessar modernizr.com e ler a documentação sobre ele e o restante dos recursos.

O segundo item é o recurso que ajuda a transformar esta linha de código:

!!document.createElement('canvas').getContext

Nesta linha de código:

Modernizr.canvas

Ela retorna um booliano que indica se o elemento canvas é suportado na página. Comparado com a detecção de recursos manual, o Modernizr tem a vantagem de ser uma biblioteca testada, robusta e amplamente usada que faz o trabalho pesado por você. O Twitter, o Google, a Microsoft e muitos outros usam o Modernizr, e você também pode. Com a atualização do ASP.NET MVC 3 Tools (lançada em abril de 2011), a Microsoft já inclui o Modernizr nas novas aplicações ASP.NET MVC. Obviamente, tudo que fiz até agora foi detectar se o elemento <canvas> é suportado. Ainda não disse nada sobre o que fazer em seguida. Após determinar através da detecção se o recurso está ou não disponível para o navegador, o passo seguinte é criar uma lógica condicional que impeça a execução de determinado código caso o recurso não exista ou que execute um caminho alternativo, semelhante a este:

if (Modernizr.canvas) {

  // Execute canvas code here.

}

A adição de recursos ao site baseada na presença de recursos adicionais no navegador é chamada de "aperfeiçoamento progressivo", pois melhora a experiência quando a capacidade do navegador é maior. No outro extremo está a degradação imperceptível de recursos. Em vez de causar erros ou falhas no navegador, a ausência de certos recursos apenas diminui a funcionalidade apresentada ao usuário, ou gera funcionalidades alternativas. Nos navegadores mais antigos, a degradação imperceptível não precisa ser a opção padrão. Em muitos casos, nem mesmo é a melhor opção. Com a assistência do Modernizr, você pode usar um dos muitos polyfills disponíveis para adicionar recursos similares aos do HTML5 aos navegadores com suporte inferior.

O que são polyfills?

De acordo com o site do Modernizr, um polyfill é um "shim de JavaScript que replica a API padrão nos navegadores mais antigos". "API padrão" se refere a um determinado recurso ou tecnologia HTML5, como o canvas. "Shim de Javascript" significa que você pode carregar códigos ou bibliotecas JavaScript dinamicamente para simular essas APIs em navegadores que não têm suporte para elas. Por exemplo, um polyfill de Localização Geográfica adiciona um objeto de localização geográfica global ao objeto do navegador, bem como a função getCurrentPosition e o objeto de retorno de chamada "cords", tudo conforme a API de Localização Geográfica World Wide Web Consortium (W3C). Como o polyfill imita uma API padrão, você pode se basear nela para desenvolver para todos os navegadores, sem ter problemas no futuro e com o objetivo de remover o polyfill assim que o suporte atingir o ponto ideal. Nenhum trabalho adicional será necessário.

Ao incluir uma referência ao Modernizr na minha página, eu obtenho um benefício de polyfilling imediato, como mostra o exemplo da Figura 3. A página foi renderizada sem estilo porque o Internet Explorer 8 não reconhece marcas como <article> e <header>. E como não as reconheceu, ele não as adicionou ao DOM, o meio usado pelo CSS para selecionar os elementos a serem estilizados.

Quando adicionamos a marca <script> e a referência ao Modernizr, o resultado é uma página com estilo, como na Figura 4. Esse benefício se deve ao fato de o Modernizr adicionar manualmente todas as novas marcas HTML5 ao DOM usando JavaScript (document.CreateElement('nav')), o que permite que elas sejam selecionadas e estilizadas pelo CSS.

Figura 4 Página HTML5 no Internet Explorer 8 com a ajuda do Modernizr

Fora a inclusão do suporte aos novos elementos de HTML5 no Internet Explorer, a biblioteca Modernizr não vem com nenhum polyfill adicional. Você mesmo tem que fornecê-los, ou a partir dos seus próprios scripts ou da lista crescente de opções documentadas no site do Modernizr. Na versão 2.0, o Modernizr oferece um carregador de scripts condicional (baseado no yepnope.js—yepnopejs.com) que permite fazer um download assíncrono de bibliotecas de polyfilling quando necessário. O uso do Modernizr com uma ou mais bibliotecas de polyfilling que forneçam os recursos necessários é uma combinação poderosa.

Usando polyfills para simular a funcionalidade do HTML5

No caso do canvas, você pode replicar (via polyfill) níveis de suporte no Internet Explorer 8 e em navegadores anteriores com a ajuda do Modernizr e de uma biblioteca JavaScript chamada excanvas, que inclui no Internet Explorer 6, 7 e 8 o suporte a canvas no nível da API. Faça o download da excanvas na página bit.ly/bSgyNR bit.ly/bSgyNR e, depois de adicioná-la à pasta de scripts, acrescente código ao bloco de script da sua página, como mostra a Figura 5.

Figura 5 Usando o Modernizr para replicar o suporte a canvas por meio de um polyfill

Modernizr.load({

  test: Modernizr.canvas,

  nope: '../js/excanvas.js',

  complete: function () {

    Modernizr.load('../js/html5CanvasLogo.js');

  }

}]);

Aqui, estou usando o carregador de scripts do Modernizr para especificar três coisas:

  1. Uma expressão booliana para teste
  2. Um caminho para o carregamento de um script se a avaliação da expressão retornar "falso"
  3. Um retorno de chamada para ser executado após a verificação ou o carregamento do script

No contexto do canvas, só preciso disso para adicionar inteligência e polyfilling à aplicação. O Modernizr carrega o excanvas.js de modo assíncrono apenas para os carregadores que não tiverem suporte para o canvas, e depois carrega a minha biblioteca de scripts para desenhar o logotipo do HTML5 na página.

Vamos ver outro exemplo para enfatizar o valor do Modernizr. Os mais detalhistas devem ter notado que o site estilizado na Figura 4 não é exatamente igual à página original renderizada no Internet Explorer 9 e mostrada na Figura 1. A página vista no Internet Explorer 8 não tem sombras nas bordas (box shadow) e cantos arredondados (border radius), e eu não poderia enviar um site tão legal sem esses efeitos, portanto vamos apelar novamente para o Modernizr.

Como no caso do canvas, o Modernizr informa que os módulos CSS3 não são suportados, mas cabe a mim fornecer uma biblioteca para replicá-los via polyfill. Felizmente, existe uma biblioteca chamada PIE (css3pie.com) que fornece os dois módulos.

Para adicionar suporte ao border-radius e ao box-shadow, posso acrescentar o código da Figura 6 ao meu script após o download da PIE. Desta vez, vou testar para ver se um dos módulos (border-radius ou box-shadow) é suportado, em vez de supor que sempre há suporte para ambos ou para nenhum dos dois. Se um deles não for suportado, vou carregar a PIE.js dinamicamente. Quando a PIE terminar de carregar, vou executar um jQuery para selecionar todas as marcas <article> e chamar a função PIE.attach, que adiciona suporte aos estilos border-radius e box-shadow já definidos no meu CSS. O resultado é mostrado na Figura 7.

Figura 6 Usando o Modernizr e a PIE para adicionar suporte a CSS3

Modernizr.load({

  test: Modernizr.borderradius || Modernizr.boxshadow,

  nope: '../js/PIE.js',

  callback: function () {

    $('article').each(function () {

      PIE.attach(this);

    });

  }

});

Figura 7 Suporte a CSS3 com Modernizr e PIE

Usando polyfills para gerar uma degradação imperceptível de recursos

Além de oferecer técnicas de polyfilling em bibliotecas, o Modernizr pode ajudar a realizar uma degradação imperceptível dos recursos da aplicação.

Digamos que eu tenha um controle do Bing Maps em uma página Web e queira usar a Localização Geográfica — da qual falaremos mais em outro artigo — para determinar a localização atual do usuário e marcá-la com uma "tachinha" no controle de mapa.

A Localização Geográfica é suportada nas versões recentes de todos os navegadores, mas não nos mais antigos. Também é um pouco complicado fornecer suporte total à API de Localização Geográfica apenas por meio do JavaScript, e embora existam polyfills para Localização Geográfica, eu resolvi reduzir os recursos da aplicação de forma imperceptível. Quando o navegador do usuário não tiver suporte para a Localização Geográfica, vou fornecer um formulário para que ele insira a localização manualmente, e então vou usá-lo para posicionar e fixar o local no mapa.

Com o Modernizr, é uma simples chamada de carregamento para um dos dois scripts que criei, como mostra a Figura 8. Nesse caso, estou testando a propriedade Modernizr.geolocation. Se for verdadeiro ("yep"), vou carregar o script fullGeolocation.js, que usará a API de Localização Geográfica para encontrar o meu local (com a minha permissão) e posicioná-lo no mapa, como mostra a Figura 9. Se, por outro lado, o teste der falso ("nope"), vou carregar um script de fallback que exibe um formulário de endereço na minha página. Quando o usuário enviar o formulário, usarei o endereço fornecido para centralizar e marcar o mapa, como mostra a Figura 10. Assim, a página proporciona uma ótima experiência para os navegadores modernos e reduz sua capacidade de forma imperceptível até atingir uma alternativa razoável para os antigos.

Figura 8 Usando o Modernizr para realizar uma degradação imperceptível de recursos

Modernizr.load({

  test: Modernizr.geolocation,

  yep: '../js/fullGeolocation.js',

  nope: '../js/geolocationFallback.js'

});

Figura 9 Mapeamento com a Localização Geográfica

Figura 10 Fornecendo suporte de fallback à Localização Geográfica

Em vista da grande base de usuários que ainda não atualizou os navegadores, é compreensível que as pessoas analisem os recursos avançados do HTML5 e decidam que seus sites ainda não estão preparados. Mas existem ótimas soluções que não só possibilitam uma degradação imperceptível de capacidades, como também fornecem os recursos necessários para trazer esses navegadores antigos para o presente e permitir que os usuários experimentem já o HTML5. Ao longo deste artigo, vimos que com a detecção de recursos, o Modernizr e o polyfilling, é possível adotar o HTML5 para o segmento crescente de usuários de navegadores modernos sem deixar as outras pessoas para trás.


Brandon Satrom trabalha como divulgador para desenvolvedores na Microsoft em Austin, Texas. Seu blog está disponível em UserInexperience.com e ele pode ser encontrado no Twitter em twitter.com/BrandonSatrom.

Obrigado aos seguintes especialistas técnicos por revisarem este artigo: Damian Edwards, Scott Hunter e Clark Sell

Deixe um comentário...


Outros recursos em destaque

Tweets recentes sobre o HTML5

Tópicos do HTML5 no Slashdot