Criando aplicativos com o HTML5

Nenhum navegador ficará para trás: uma estratégia de adoção do HTML5

Brandon Satrom

Baixar o código de exemplo

Existe bastante coisa com o que se empolgar no HTML5. Com nova marcação, recursos de CSS e APIs de JavaScript, o escopo do que é possível na Web está crescendo rapidamente. Acrescente a isso a constante demonstração de superioridade entre fornecedores de navegadores, e a lista de recursos interessantes se expandirá quase que diariamente. De compilações noturnas a versões de canal de desenvolvedor e visualizações de plataforma regulares, os navegadores estão mudando rapidamente e os desenvolvedores da Web de todos os lugares estão juntos nessa estimulante jornada.

Mas, embora o HTML5 tenha se tornado uma febre nas comunidades de desenvolvimento e navegador, a grande maioria das pessoas na Web não está utilizando os novos navegadores e as novas versões que nós estamos usando. Se for um desenvolver da Web em um grande departamento de desenvolvimento ou uma empresa com uma grande base de usuários, você provavelmente já sabe disso. Mesmo se estiver trabalhando em um pequeno departamento ou se começar a fornecer algum serviço via Web, você provavelmente gasta bastante tempo assegurando que seu site atende ao máximo de navegadores e versões de navegadores possível.

De acordo com essa realidade, é fácil perceber o HTML5 não em termos de ele estar pronto para ser utilizado hoje, mas de você estar pronto para ele. Por exemplo, vamos supor que você tenha criado uma página com algumas das novas marcas semânticas (como <header> e <article>), tenha acrescentado alguns recursos novos de CSS (como border-radius e box-shadow) e, até mesmo, tenha adicionado um elemento <canvas> para desenhar um logotipo do HTML5 em sua página.

Em navegadores mais novos, como o Internet Explorer 9, o Firefox 4 e posterior ou o Google Chrome, isso será renderizado conforme exibido na Figura 1. Mas, se você tentar carregar essa página no Internet Explorer 8 ou posterior, verá algo mais parecido com o exibido na Figura 2: uma página totalmente quebrada.

Semantic Page with Styles and an HTML5 <canvas> Element, Rendered in Internet Explorer 9
Figura 1 Uma página semântica com estilos e um elemento <canvas> do HTML5 renderizada no Internet Explorer 9

The Same Semantic Page, Rendered in Internet Explorer 8 with No Styles and No <canvas>
Figura 2 A mesma página semântica, renderizada no Internet Explorer 8, sem nenhum estilo e nenhum elemento <canvas>

Eu não o culparia se você verificasse todos os excelentes recursos do HTML5 e, depois de ter uma experiência como essa, dissesse a si mesmo que o melhor a fazer é esperar. É fácil concluir que, pronto ou não, o HTML5 não está totalmente pronto para você ou seus usuários.

Antes de tomar a decisão de definir uma data em 2022 para dar outra chance para o HTML5, eu recomendo que leia o restante deste artigo. O meu objetivo neste mês é fornecer a você estratégias práticas de como é possível adotar tecnologias do HTML5 hoje sem terminar com o tipo de redução ilustrada na Figura 2. Neste artigo, abordarei:

  1. Detecção de recursos versus detecção de UA (user agent - agente do usuário)
  2. Suporte retroativo com JavaScript
  3. Redução gradual

Esses três assuntos devem informá-lo muito sobre o que é necessário saber para criar sites da Web para uma amplo espectro de navegadores. Quando terminarmos, você terá uma sólida estratégia de adoção de tecnologias do HTML5 com confiança e sem demora. Você também terá algumas ferramentas que poderá usar para aprimorar progressivamente os sites para navegadores mais novos e, ao mesmo tempo, reduzir gradualmente para outros.

A importância da detecção de recursos

A fim de fornecer experiências estáveis e consistentes entre navegadores, os desenvolvedores frequentemente precisam ter algumas informações sobre o navegador de um usuário. Historicamente, era comum determinar essas informações com o JavaScript desta maneira:

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, é amplamente utilizada para determinar qual é o navegador que está solicitando a sua página. A lógica é que, ao conhecer o navegador do usuário (Internet Explorer 7, por exemplo), você pode tomar decisões em tempo de execução sobre quais recursos de seu site devem ser habilitados ou desabilitados. A detecção de UA é o equivalente a dizer ao navegador: “quem é você?”. Para obter uma análise mais profunda sobre a detecção de UA e outras técnicas de detecção, consulte bit.ly/mlgHHY.

O problema dessa abordagem é que os navegadores podem ser feitos para mentir. A cadeia de caracteres de UA é uma parte da informação configurada pelo usuário que não fornece realmente uma imagem 100% precisa do navegador em questão. Além disso, como essa técnica foi amplamente adotada, muitos fornecedores de navegador adicionam conteúdo extra a suas próprias cadeias de caractere de UA como uma maneira de iludindo os scripts para desenhar suposições incorretas sobre qual navegador estava sendo usado, enganando a detecção. Agora, alguns navegadores incluem até mesmo um recurso que permite que os usuários alterem a cadeia de caracteres de seu UA com apenas alguns cliques.

O objetivo da detecção de UA nunca foi saber o navegador do usuário, nem sua versão. E, certamente, ela não era destinada a fornecer a você uma via para dizer a seus usuários para “baixarem outro navegador” se estivessem usando um navegador que não fosse de sua preferência — embora essa técnica seja utilizada por algumas pessoas. Os usuários podem escolher o navegador que utilizam, e nossa responsabilidade como desenvolvedores é fornecer a experiência mais confiável e consistente, e não impor uma opinião de preferência de navegador sobre eles. O objetivo da detecção de UA sempre foi fornecer a você uma imagem precisados recursos que podem ser aproveitados no navegador atual do usuário. O próprio conhecimento do navegador é apenas um meio para essa informação.

Atualmente, existem alternativas para a detecção de UA, e uma delas com a popularidade crescente — graças, em parte, ao jQuery e ao Modernizr — é chamada de detecção de objetos ou recursos. Esses termos são, em grande parte, intercambiáveis, mas vou utilizar “detecção de recursos” neste artigo.

O objetivo da detecção de recursos é determinar se um recurso específico tem suporte no navegador atual do usuário. Se a detecção de UA é como perguntar ao navegador “quem é você”, a detecção de recursos é como perguntar ao navegador “do que você é capaz” — uma pergunta muito mais direta e uma maneira muito mais confiável para você fornecer funcionalidades condicionais aos usuários. É muito mais difícil de os usuários e os navegadores falsificarem ou relatarem incorretamente o suporte a recursos, pressupondo que os scripts de detecção de recursos sejam corretamente implementados.

Detecção manual de recursos

Dessa maneira, qual a aparência da detecção de recursos, em oposição ao exemplo de detecção de UA? Para responder a isso, vejamos como corrigir os problemas surgidos ao exibir minha página em HTML5, demonstrados na Figura 1, no Internet Explorer 8, em vez de no Internet Explorer 9. A marcação para essa página está listada na Figura 3.

Figura 3 Uma página com nova marcação HTML5 semântica

<!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, conforme mostrado nas Figuras 1 e 2, são drásticas. Para os iniciantes, minha página é totalmente sem estilo, como se o CSS dessa página não existisse. Além disso, estou sentindo falta do sofisticado escudo do HTML5 na parte inferior da página. Cada um desses problemas pode ser corrigido facilmente, e a detecção de recursos é a primeira etapa para identificar o problema.

A causa de ambos os problemas é simples: <header>, <article> e <canvas> são elementos HTML não válidos no que diz respeito ao Internet Explorer 8 e, por isso, não posso trabalhar com eles. Para resolver a questão do <canvas>, em vez de usar a detecção de UA para determinar o navegador/a versão que está em uso, eu gostaria de perguntar ao navegador, via JavaScript, se o elemento <canvas> e suas APIs de JavaScript têm suporte. A minha verificação de recursos para canvas é semelhante a isso:

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

Essa instrução faz algumas coisas. Primeiro, ela usa a negação dupla (!!) para forçar que valores indefinidos sejam explicitamente falsos. Em seguida, cria manualmente um novo elemento canvas e o anexa ao DOM. Por fim, ela invoca getContext, uma nova função disponível para elementos <canvas> como uma maneira de manipular a API de Canvas via JavaScript. Se eu estiver usando o Internet Explorer 9, essa instrução retornará true. Se estiver usando o Internet Explorer 8, getContext retornará “undefined”, que a negação dupla irá impor como false.

Essa é a detecção de recursos em sua forma mais básica. Com essa instrução e outras como ela, eu agora tenho uma maneira mais confiável de consultar o suporte a recursos no navegador. Para obter mais informações sobre a detecção manual de recursos, visite diveintohtml5.info/everything.html.

Usando o Modernizr para a detecção de recursos

A detecção manual de recursos é, certamente, uma melhoria na detecção de UA, mas essa abordagem ainda deixa o trabalho pesado para você em relação à detecção de disponibilidade de um recurso e à decisão do que fazer se o recurso não existir. E, embora o exemplo de canvas tenha sido apenas uma simples solicitação de uma linha de código, esse não é o caso para todos os recursos que você talvez queira detectar — nem o código de detecção será o mesmo em todos os navegadores. A detecção de suporte para módulos CSS3 que utilizei anteriormente (border-radius e box-shadow), por exemplo, pode ser um pouco mais complicada.

Felizmente, o Modernizr (modernizr.com) oferece uma abordagem melhor. O Modernizr é uma biblioteca JavaScript que “… detecta a disponibilidade de implementações nativas para tecnologias da Web da próxima geração, ou seja, recursos provenientes de especificações do HTML5 e do CSS3”. A adição de uma referência ao Modernizr em suas páginas fornece quatro recursos importantes:

  1. Uma lista abrangente de recursos com suporte que é adicionada à sua marcação de maneira inteligente, o que habilita definições de CSS condicionais.
  2. Um objeto JavaScript que auxilia na detecção de recursos com base em script.
  3. Todas as novas marcas HTML5 adicionadas ao DOM em tempo de execução, para beneficiar navegadores com o Internet Explorer 8 e versões anteriores do Internet Explorer (mais sobre esse assunto a seguir).
  4. Um carregador de scripts para carregar suportes retroativos em suas páginas de maneira condicional.

Não vamos mais discutir o primeiro item neste artigo e, por isso, eu recomendo que vá até o site modernizr.com e verifique a documentação sobre isso e o restante dos recursos.

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

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

Nesta linha de código:

Modernizr.canvas

Isso retorna um booleano que indica se o elemento canvas tem suporte na página. O melhor da utilização do Modernizr, em oposição à realização de sua própria detecção de recursos, é que o Modernizr é uma biblioteca testada, robusta e amplamente utilizada que faz o trabalho pesado para você. Twitter, Google, Microsoft e muitos outros utilizam o Modernizr, e você também pode usá-lo. Com a atualização das ferramentas do ASP.NET MVC 3 (lançada em abril de 2011), a Microsoft passou a fornecer o Modernizr juntamente com os novos aplicativos do ASP.NET MVC. Obviamente, tudo o que fiz até o momento foi detectar se existe suporte para o elemento <canvas>. Eu não disse nada sobre o que fazer em seguida. De acordo com o conhecimento, por meio da detecção de recursos, de que um recurso está ou não disponível para um navegador, uma etapa seguinte comum é a criação de alguma lógica condicional que impeça a execução de determinados códigos se um recurso não existir ou que execute um caminho alternativo, semelhante a isto:

 

if (Modernizr.canvas) {
  // Execute canvas code here.
}

A inclusão de recursos em seu site com base na existência de recursos de navegador adicionais é conhecida como “aprimoramento progressivo”, pois você melhora a experiência para oferecer um navegador mais capacitado. No outro extremo do espectro está a “redução gradual”, na qual a ausência de determinados recursos não causa erros ou falhas do navegador, mas, em vez disso, apresenta ao usuário uma diminuição de recursos ou um recurso alternativo. Para navegadores mais antigos, a redução gradual não precisa ser a opção padrão. Em muitos casos, ela talvez nem seja a melhor opção. Em vez disso, com a ajuda do Modernizr, você geralmente pode usar um dos muitos suportes retroativos de navegador disponíveis para adicionar recursos do tipo do HTML5 a navegadores sem suporte.

O que são suportes retroativos?

De acordo com o site do Modernizr, um suporte retroativo é “uma correção de JavaScript que replica a API padrão para navegadores antigos”. “API padrão” refere-se a uma determinada tecnologia ou determinado recurso do HTML5, como canvas. “Correção de JavaScript” indica que você pode carregar códigos ou bibliotecas JavaScript dinamicamente que simulem essas APIs nos navegadores que não oferecem suporte a elas. Por exemplo, o suporte retroativo a uma Localização Geográfica pode adicionar o objeto de localização geográfica global ao objeto de navegador, além de adicionar a função getCurrentPosition e o objeto de retorno de chamada “cords”, tudo conforme definido pela API de Localização Geográfica do W3C (World Wide Web Consortium). Como o suporte retroativo simula uma API padrão, você pode desenvolver nessa API de uma maneira que garanta a durabilidade para todos os navegadores, com o objetivo de remover o suporte retroativo quando o suporte alcançar uma importância crítica. Nenhum trabalho adicional é necessário.

Ao adicionar uma referência ao Modernizr em minha página, eu imediatamente obtenho o benefício de suporte retroativo relacionado ao exemplo na Figura 3. A página foi renderizada sem estilo porque o Internet Explorer 8 não reconhece marcas como <article> e <header>. E, por não reconhecê-las, ele não as adiciona no DOM, que é a maneira como o CSS seleciona os elementos para serem estilizados.

Quando adiciono uma marca <script> e uma referência ao Modernizr em minha página, o resultado é uma página estilizada, como na Figura 4. Esse benefício é obtido porque o Modernizr adiciona manualmente todas as novas marcas HTML5 ao DOM usando JavaScript (document.CreateElement(‘nav’)), o que permite que as marcas sejam selecionadas e estilizadas usando CSS.

An HTML5 Page in Internet Explorer 8, with the Help of Modernizr
Figura 4 Uma página HTML5 no Internet Explorer 8 com a ajuda do Modernizr

Além de seu uso para a inclusão de suporte a novos elementos do HTML5 no Internet Explorer, a biblioteca do Modernizr não fornece nenhum suporte retroativo adicional pronto para uso. Eles devem ser fornecidos por você, a partir de seus próprios scripts ou da lista em constante crescimento de opções documentas no site do Modernizr. A partir da versão 2.0, o Modernizr fornece um carregador de scripts condicional (com base em yepnope.js — yepnopejs.com) que ajuda você a baixar bibliotecas de suporte retroativo de maneira assíncrona apenas quando necessário. O uso do Modernizr com uma ou mais bibliotecas de suporte retroativo que fornecem os recursos de que você necessita é uma poderosa combinação.

Usando suportes retroativos para simular funcionalidades do HTML5

No caso do canvas, você pode fornecer suporte retroativo ao Internet Explorer 8 e anteriores com a ajuda do Modernizr e de uma biblioteca JavaScript chamada excanvas, que adiciona o suporte a canvas no nível da API para o Internet Explorer 6, o Internet Explorer 7 e o Internet Explorer 8. Você pode baixar a excanvas em bit.ly/bSgyNR e, depois de adicioná-la à sua pasta de scripts, você poderá adicionar algum código a um bloco de script em sua página, conforme mostrado na Figura 5.

Figura 5 Usando o Modernizr para oferecer suporte retroativo a canvas

 

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 booleana a ser testada.
  2. Um caminho para um script a ser carreado se a expressão for avaliada como falsa.
  3. Um retorno de chamada a ser executado após a verificação ou o carregamento do script ser concluído.

No contexto de canvas, isso é tudo o que preciso para adicionar alguma inteligência e dar suporte retroativo ao meu aplicativo. O Modernizr carregará de maneira assíncrona o excanvas.js apenas para navegadores que não oferecem suporte a canvas e, em seguida, carregará minha biblioteca de scripts para desenhar o logotipo do HTML5 na página.

Vejamos outro exemplo para ressaltar o valor do Modernizr. Você talvez tenha notado que os detalhes do site estilizado na Figura 4 não são exatamente os mesmos da página original, renderizada no Internet Explorer 9 e demonstrada na Figura 1. A página, conforme exibido no Internet Explorer 8, não possui um sombreamento da caixa nem cantos arredondados, e eu não poderia entregar esse incrível site sem ambos; por isso, vamos apelar para o Modernizr novamente para obter ajuda.

Da mesma maneira que com o canvas, o Modernizr pode informar que os módulos CSS3 não têm suporte, mas cabe a mim fornecer uma biblioteca para dar suporte retroativo a eles. Felizmente, existe uma biblioteca chamada PIE (css3pie.com) que fornece os dois módulos em uma única biblioteca.

Para adicionar suporte a border-radius e box-shadow, eu posso incluir o código da Figura 6 em meu script depois de baixar a biblioteca PIE. Desta vez, vou testar para verificar se algum dos módulos border-radius ou box-shadow tem suporte (em vez de pressupor que ambos sempre têm ou não suporte) e, se um deles não tiver suporte, carregarei PIE.js dinamicamente. Depois do carregamento de PIE, executarei uma parte de jQuery para selecionar todas as minhas marcas <article> e chamar a função PIE.attach, que adicionará suporte aos estilos border-radius e box-shadow já definidos no CSS. O resultado está representado na Figura 7.

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

Modernizr.load({
  test: Modernizr.borderradius || Modernizr.boxshadow,
  nope: '../js/PIE.js',
  callback: function () {
    $('article').each(function () {
      PIE.attach(this);
    });
  }
});

CSS3 Support with Modernizr and PIE
Figura 7 Suporte ao CSS3 com o Modernizr e a PIE

Usando suportes retroativos para auxiliar na redução gradual

Além de usar as técnicas de suporte retroativo discutidas neste artigo, você também pode aproveitar o Modernizr para ajudar nos casos em que deseja reduzir gradualmente seus aplicativos, em vez de oferecer suporte retroativo em outra biblioteca.

Digamos que possuo um controle do Bing Maps em uma página da Web e eu desejo usar a Localização Geográfica — que abordaremos mais profundamente em outro artigo — para encontrar a localização atual do usuário e colocar essa localização como um pino no controle de mapa.

Embora a Localização Geográfica tenha suporte em versões recentes de todos os navegadores, isso não ocorre em navegadores antigos. Também é um pouco mais complicado fornecer suporte total à API de Localização Geográfica somente via JavaScript e, embora existam suportes retroativos para a Localização Geográfica, eu decidi reduzir gradualmente meu aplicativo. Nos casos em que o navegador do usuário não oferecer suporte à Localização Geográfica, eu irei fornecer um formulário que poderá ser usado para inserir a localização manualmente, que eu utilizarei posteriormente para posicionar e marcar o mapa.

Com o Modernizr, isso é uma simples chamada de carga para um dos dois scripts criados, conforme ilustrado na Figura 8. Nesse caso, estou testando a propriedade Modernizr.geolocation. Se for verdadeira (“yep”), meu script fullGeolocation.js será carregado, e ele utilizará a API de Localização Geográfica para encontrar minha localização (com a minha permissão) e colocá-la em um mapa, conforme ilustrado na Figura 9. Caso contrário, se o teste retornar falso (“nope”), um script de fallback será carregado, exibindo um formulário de endereço em minha página. Quando o usuário enviar o formulário, o endereço fornecido será usado para centralizar e marcar o mapa, conforme ilustrado na Figura 10. Dessa maneira, minha página fornece uma excelente experiência para navegadores modernos e, ao mesmo tempo, torna a redução gradual uma alternativa razoável para navegadores mais antigos.

Figura 8 Usando o Modernizr para fornecer redução gradual

Modernizr.load({
  test: Modernizr.geolocation,
  yep: '../js/fullGeolocation.js',
  nope: '../js/geolocationFallback.js'
});

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

Providing Geolocation Fallback Support
Figura 10 Fornecendo suporte ao fallback da Localização Geográfica

É fácil ver alguns dos recursos avançados do HTML5 e, diante de uma grande base de usuários ainda em navegadores antigos, decidir que seu site ainda não está totalmente pronto para eles. Mas já existem soluções excelentes disponíveis que auxiliam na redução gradual e também fornecem a capacidade de trazer esse navegadores antigos para o presente, de forma que seus usuários possam usufruir da experiência do HTML5 agora mesmo. Ao longo deste artigo, você viu que, com a detecção de recursos, o Modernizr e o suporte retroativo, é possível adotar imediatamente o HTML5 para o crescente segmento de usuários com um navegador moderno — e, ao mesmo tempo, cuidar para não deixar o restante de sua base de usuários para trás.

Brandon Satrom trabalha como desenvolvedor e divulgador da Microsoft em Austin, Texas. Ele mantém um blog em UserInexperience.com e pode ser seguido no Twitter em twitter.com/BrandonSatrom.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Damian EdwardsScott Hunter e Clark Sell