Elementos base do desenho adaptável

Este artigo discute os componentes essenciais de desenho responsivo, com ligações para outros artigos que ajudam a aprofundar, se for necessário.

Para os desenvolvedores da Web, hoje em dia é bastante comum serem chamados a criar um site ou aplicação Web que muda a sua interface de acordo com o navegar (browser) ou dispositivo que lhe estiver a aceder, e assim proporcionar uma experiência ótima. Uma possível abordagem a este desafio é criar versões diferentes da aplicação ou site para diferentes plataformas ou navegadores e servi-los de forma apropriada depois de detetar qual o navegador ou plataforma que está a olhar para o site. Mas esta solução seria cada vez mais ineficiente: os métodos para determinar o navegador são intrinsecamente propícios a erros, e manter várias cópias do código pode tornar-se um pesadelo.

Em geral é muito melhor criar uma única versão do código que não toma decisões  com base no navegador ou plataforma, mas que faz testes a fim de saber quais as funcionalidades suportadas pelo navegador, ou quais os parâmetros do mesmo. Depois, este código é ajustado em função das funcionalidades disponíveis. Costuma-se chamar a isto desenho responsivo ou desenho adaptativo (estes dois termos referem-se a abordagens diferentes ao mesmo problema; para uma discussão sobre as diferentes entre ambos, leia Responsive design versus adaptive design).

Esta solução é muito mais fiável, a sua manutenção é mais fácil, e pensa mais no futuro. Já não traz o problema que é desenvolver mais versões do site à medida que surgem novos navegadores e plataformas, pois o código é ajustado à medida que os navegadores e as funcionalidades existentes mudam.

Ainda assim tem desvantagens. Se o conteúdo, disposição (layout) e funcionalidade precisam de ser extremamente diferentes para cada dispositivo, pode não ser uma boa abordagem. Além disso, pegar num site que já existe e adicionar-lhe características de desenho responsivo / adaptável, para ser mais amigo dos dispositivos móveis, pode implicar um esforço maior do que simplesmente criar uma site ou aplicação separado, especialmente se for um site empresarial em expansão. Leia mais sobre vantagens e desvantagens de desenho adaptável.

Pode ler a nossa discussão sobre desenho adaptável, se precisar de peceber melhor o contexto e as bases.

Grelhas fluídas

O melhor sítio para começar é com medições fluídas do layout da aplicação — essencialmente, isto significa utilizar uma combinação de percentagens e em/rem para dar tamanho ao texto e contentores, em vez de unidades fixas como pixel. Desta forma, o layout adapta-se a diferentes dimensões do viewport, o que traz muitas vantagens. Vejamos um exemplo.

Escrevemos um protótipo simples-mas-divertido de uma aplicação chamada Snapshot, a qual grava um stream de vídeo da sua webcam (usando getUserMedia()) e depois permite capturar imagens estáticas desse stream (com a <canvas> do HTML5), e guarda-os numa galeria. Depois pode ver as imagens capturadas e apagá-las. Outros artigos discutem esta funcionalidade mais detalhadamente, mas agora só nos interessa o layout.

Note: Pode encontar a aplicação Snapshot no Github; veja o código e ajude a melhorar. Também pode ver o Snapshot ao vivo. Note que getUserMedia() é uma tecnologia experimental, que de momento apenas funciona no Google Chrome e Firefox desktop. No futuro planeia-se mais funcionalidade e melhor organização do Snapshot.

O layout na versão desktop do Snapshot consiste em três colunas, que mostram o stream, imagem de captura e a galeria, respetivamente.

A marcação é muito simples:

<x-deck selected-index="0">
  <x-card>
    …
  </x-card>
  <x-card>
    …
  </x-card>
  <x-card>
    …
  </x-card>
</x-deck>

Note: Estes elementos "x-" esquisitos não devem ser familiares; fazem parte do Brick, a biblioteca da Mozilla de elementos UI para aplicações web móveis. Utilizámos o Brick para criar o layout móvel do Snapshot, sobre o qual irá ler mais em baixo.

Para que fiquem lado a lado, usamos estas regras:

x-card {
  width: 100%;
}

x-card:nth-child(1), x-card:nth-child(2) {
  width: 30%;
  float: left;
  padding: 2rem;
}

x-card:nth-child(3) {
  width: 40%;
  float: left;
  height: 100%;
  overflow: auto;
  padding: 2rem;
}

Demos largura (width) 30% às primeiras duas colunas, e à terceira, 40% de largura, e deixamos as colunas flutuarem (float) à esquerda. Assim ficam lado a lado, e mantêm as mesmas proporções à medida que varia o tamanho da janela do navegador. Este é um exemplo muito simples de uma grelha, mas pode aplicar este princípio a grelhas mais complexas, conforme necessário.

Dimensões dos contornos da caixa

O espaçamento não afeta a largura e altura totais dos contentores porque mudámos a propriedade box-sizing para border-box em todos os elementos:

*, *:before, *:after {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

Basicamente, isto significa que, agora, width e height definem as dimensões de um elemento incluindo os conternos, e não só o conteúdo. Por isso, ao fixar width: 40%, a largura da caixa será 40%  do pai, e larguras de padding ou border serão subtraídas da largura do conteudo, em vez de adicionadas. Isto é muito útil! Leia mais no artigo * { Box-sizing: Border-box } FTW, escrito pelo Paul Irish.

Flexible replaced elements

Até agora tudo bem, mas há algumas questões à espera de se chegarem à frente. Primeiro, vamos ver o que acontece quando incluímos os elementos <video> e <img> nas duas primeiras colunas, nus e sem estilo.

Como o tamanho dos elementos substituídos é ditado pelo tamanho dos média inseridos neles, e este média tem tamanho fixo, explodem para fora dos elementos que os contem e fazem uma confusão no layout. É horrível, mas em geral este problema é resolvido com CSS simples:

img, video {
  max-width: 100%;
}

Isto diz aos elementos substituídos para permanecerem dentro da largura do elementos que os contem, em qualquer circunstância. Contudo, se não forem tão largos como os elementos pai, não aumenta para os preencher. No exemplo da fotografia, o código final é um pouco diferente:

x-card:nth-child(1) video, x-card:nth-child(2) img {
  width: 100%;
    …
}

Isto porque, no nosso caso, queremos de facto que vídeo e imagem preencham o elemento pai em qualquer circunstância — uma diferença subtil mas importante em relação a max-width — logo, terão sempre o mesmo tamanho. O vídeo muda de tamanho dinamicamente, mas as capturas de ecrã não, portanto, ao ampliar o ecrã podia obter-se um layout desorganizado, com elementos de dimensões diferentes, quando se utiliza max-width: 100%, por exemplo:

Consultas de média

Grelhas fluídas são um ótimo começo, mas notará que em certos pontos, (conhecidos como breakpoints) o layout começa a desfazer-se. Nestes pontos vai querer retificar o problema no layout, e para o efeito pode usar consultas de média.

Nota: As consultas de média são uma funcionalidade CSS3 que permite aplicar CSS seletivamente, em função do resultado de testes a funcionalidades do média — para aprofundar as bases, leia Media queries.

Disposição típica no desktop

Como já vimos, no nosso exemplo temos um layout para computador de secretária (desktop). O mesmo é definido pelas regras CSS no topo da folha de estilos, antes de quaisquer consultas de média.

Layout de largura média

Também temos um layout de largura média, o qual pretendemos que funcione bem em tablets e portáteis com ecrã estreito. É definido pelo CSS na primeira consulta:

@media all and (max-width: 1024px) {
  x-card:nth-child(1), x-card:nth-child(2) {
    width: 50%;
  }

  x-card:nth-child(3) {
    width: 100%;
    clear: left;
  }
 
  x-card:nth-child(3) img {
    width: 20%;
  }
}

Aqui estamos a mudar larguras das colunas e a remover float na terceira coluna (e adicionar clear para acautelar comportamentos imprevisíveis de elementos flutuantes). Também alterámos largura das imagens dentro do terceiro contentor, (a galeria, que já não é uma coluna) e agira há 5 em cada linha (dantes eram 3).

Layout em ecrã estreito / telemóvel

Por fim temos layout para ecrãs estreitos, adequado para aplicações móveis ou "open Web apps" (por exemplo, uma aplicação do Firefox OS). Este foi criado em várias partes. Primeiro, como esperado, há uma consulta de média no CSS. Como é bastante comprida, vamos analiśa-la aos poucos:

@media all and (max-width: 480px) {  
  x-card:nth-child(1), x-card:nth-child(2), x-card:nth-child(3) {
    width: 100%;
    float: none;
    padding: 0;
  }
 
  button {
    margin-top: 0;
    border-radius: 0;
  }
 
  x-card:nth-child(1) video, x-card:nth-child(2) img {
    border-radius: 0px;
    border: none;
    padding: 0;
    background-color: 0;
  }

Este primeiro bloco repõe várias coisas dos layouts mais largos que não eram necessárias para a aplicação móvel.

  x-card:nth-child(1) video, x-card:nth-child(2) img, x-card:nth-child(3) {
    margin-top: 17.5vw;
  }
 
  x-card:nth-child(1) button, x-card:nth-child(2) button {
    position: absolute;
    bottom: 0;
  }
 
  x-card:nth-child(2) button:nth-of-type(2) {
    bottom: 5.9rem;
  }
  
  x-card:nth-child(1) button {
    font-size: 7vw;
  }
 
  x-card:nth-child(2) button {
    font-size: 7vw;
  }

Estas regras estipulam o tamanho dos botões dentro dos dois primeiros cartões, e dão a todo o conteúdo uma margem superior para o conteúdo não se preder debaixo dos botões de navegação (ler em baixo). Isto é necessário porque Mozilla Brick (ler também em baixo) obriga os seus componentes a ter 100% da largura e altura do ecrã. Nestes, usámos unidades vw (viewport width) — 1vw equivale a 1% da largura do viewport. Assim as dimensões aumentam e diminuem em conjunto com a largura do viewport.

Quando se clica numa imagem da galeria, aparece um botão para removê-la e outro para cancelar remoção, e não queremos que os dois botões fiquem um em cima do outro. Na última parte desta secção, damos aos botões posição absoluta na parte de baixo dos cartões em que se encontram, para o layout ser apresentável em diferentes variações no tamanho do viewport. Depois acrescentamos uma regra que desloca o segundo botão de qualquer cartão mais para cima, num comprimento igual ao de um botão.

x-card:nth-child(3) img {
  width: 50%;
}

Esta regra muda a largura das imagens da galeria para aparcerem 2 em cada linha.

  nav {      
    width: 100%;
    position: absolute;
    z-index: 1000;
     
    display: -webkit-flex;
    display: -moz-flex;
    display: -ms-flexbox;
    display: flex;
  }
 
  nav button {
    font-size: 6.8vw;
    
    -webkit-flex: 1;
    -moz-flex: 1;
    -ms-flex: 1;
    flex: 1;
    
    border-left: 1px solid rgba(100,100,100,0.4);
  }
 
  nav button:first-child {
    border-left: 0;
  }
}

Por fim, mudamos o valor de display do elemento <nav> para flex, de forma a que seja apresentado (estava none no CSS por omissão, no incío da folha de estilos, pois não era necessário nos outros formatos). Depois damos posição absoluta e z-index para que não ocupe espaço no fluxo do documento, e fique sobre as x-cards (foi por isso que há bocado demos margem superior às x-cards).

A seguir, o font-size dos botões é 6.8vw. Porquê? Porque a margem superior dos x-cards ficou 17vw anteriormente. Todos os botões na aplicação têm line-height igual a 2.5 (veja o CSS por omissão no início da folha). E 6.8 x 2.5 = 17.

Por último, utilizámos flex: 1; para os botões ocuparem sempre a mesma proporção de espaço na mesma linha. Vejamos a imagem em baixo o layout móvel:

single column layout for mobile app view, with three buttons to navigate between cards, an image viewer, and a Save Picture button at the button.Mas ainda há truques na manga para este layout de aplicação móvel! Como referimos anteriormente, utilizámos Mozilla Brick, uma coleção pré-fabricada de componentes para IU de telemóvel. Em particular, usámos o componente deck (baralho de cartas) e o seu simpático efeito de transição entre cartas quando se pressionam os botões. Se quiese saber mais, leia Mozilla Brick: ready made UI components.

O mais relevante neste artigo é uqe não queríamos que o CSS relativo ao Brick e ficheiros JavaScript aplicados à demarcação a não ser que estivéssemos a olhar para a aplicação em aspeto móvel. Para tal, incluímos o CSS do Brick na página com recurso a um elemento <link> separado e um atributo media:

<link href="dist/brick.css" type="text/css" rel="stylesheet" media="all and (max-width: 480px)">

Aqui diz que a folha de estilo inteira só será ligada ao HTML se e só se a largura do viewport for 480px ou menos. Passando ao JavaScript, elementos <script> não aceitam atributoss media, então tem que se usar outra estratégia. Felizmente existe um conceito em JavaScript chamado window.matchMedia(), que executa outros conceitos dependendo do resultado de uma consulta de média. Abrimos o ficheiro brick.js e à volta de todo o código existente, colocámos:

if (window.matchMedia("(max-width: 480px)").matches) {
  // O código inteiro do ficheiro brick.js está aqui!
}

Assim nada dentro do ficheiro brick.js será executado a não ser que a largura do viewport seja 480px ou menos. Problema resolvido.

Ecrãs mesmos grandes

Podes ter reparado que se o viewport alargar muito (como um ecrã de cinema), o layout pára de crescer, e centra-se no espaço disponível. Isto é relativamente simples de conseguir. Poderias usar uma consulta de média a min-width para fixar a largura do elemento <body> a determinado momento:

@media all and (min-width: 1400px) {
  body {
    width: 1400px;
    margin: 0 auto;
  }
}

Mas é mais fácil aplicar a regra seguinte e retirar por completo a consulta de média:

body {
  max-width: 1400px;
  margin: 0 auto;
}

Falha na orientação

Tabém nos deparámos com problemas de orientação: o layout do tablet foi concebido para orientação em modo retrato, e fica horrível se pusermos o aparelho em modo paisagem. Para consertar isto, acrescentamos uma consulta que só tem efeito em modo paisagem:

@media all and (max-width: 480px) and (orientation: landscape) {
  nav {   
    width: auto;
    
    -webkit-flex-direction: column;
    -moz-flex-direction: column;
    -ms-flex-direction: column;
    flex-direction: column;
  }
 
  nav button {
    font-size: 6.8vh;
  }
 
  nav button {
    border-left: 0;
  }
 
  x-card:nth-child(1) video, x-card:nth-child(2) img, x-card:nth-child(3) {
    margin-top: 0;
  }
 
  x-card:nth-child(1) button, x-card:nth-child(2) button {
    font-size: 2rem;
  }
}

Isto faz o seguinte:

  • Ajusta os botões nav, mudando a direção da flexbox em que estão dispostos, e mudando tamanho de margens e letra para ficarem na vertical e não horizontal.
  • Remove a margem superior do conteúdo da x-card para evitar um fosso desagradável no topo do ecrã em modo paisagem.
  • Muda tamanho dos botões de controlo (como Tirar Foto, Apagar Foto) para não parecerem demasiado grandes e aparecerem corretamente no ecrã.

Assim obtém-se o seguinte layout:

Nota: Outra solução no que respeita à orientação pode ser simplesmente fixar a orientação da aplicação, em retrato ou paisagem. Se estiver a desenvolver uma aplicação instalada, ou uma aplicação do Firefox OS, pode fazê-lo facilmente com o campo de oritentação do manifesto. Se quer uma solução que funcione em geral nas aplicações web, pode recorrer à API de orientação do ecrã, e/ou apresentar uma mensagem que peça ao utilizador para rodar o ecrã se estiverem a usar a orientação errada (por exemplo, se window.innerWidth for maior que  window.innerHeight, assume-se que o jogo está em modo paisagem e mostra-se uma mensagem "por favor rode o ecrã").

Viewport

Um último problema a mencionar na nossa aplicação de exemplo relaciona-se com consultas de média em navegadores móveis. Se víssemos o meu exemplo num navegador móvel, não iríamos ver o simpático layout móvel. Em vez disso, veríamos a imagem em baixo.

Porque isto acontece? Curto e grosso, os navegadores móveis mentem. Não foto-realizam páginas da internet à largura verdadeira do viewport. Em vez disso, realizam as páginas a uma largura maior que a assumida (próxima da largura de um portátil), e depois encolhem o resultado para caber no ecrã do telemóvel. Isto é um mecanismo de defesa sensato — sites da velha guarda que não fazem consultas de média teriam péssima aparência se fossem realizados numa largura de 320px ou 480px. Mas não ajuda desenvolvedores web responsáveis, que escreveram layouts para ecrãs pequenos no CSS com consultas de média e querem que os dispositivos móveis as utilizem!

Existe uma maneira de anular este comportamento de fotorrealização — viewport, que está inserido nas páginas HTML sob forma da etiqueta <meta>. No meu exemplo, vamos adicioná-lo ao <head>:

<meta name="viewport" content="width=480">

Isto obriga o navegador a realizar corretamente o layout móvel da nossa aplicação — width=480 diz-lhe: "realize o HTML a 480 pixels de largura", e portanto, as consultas de média são devidamente efetuadas. Há muitas mais opções disponíveis na etiqueta meta do viewport, as quais pode aprodundar em Utilizar etiqueta meta do viewport para controlar layout em navegadores móveis.

Nota: Há uma especificação chamada adaptação de dispositivos, que define a mesma funcionalidade mas em CSS, usando uma regra "at" @viewport. Provavelmente é um local mais lógica para tal informação, mas as especificação ainda não é tão largamente suportada como a etiqueta meta do viewport, pelo que deve manter essa solução por enquanto.

Vídeo e imagens adaptáveis

Outro problema cada vez mais comum é tornar o peso (em KB) de imagens e vídeo adaptáveis tal como as dimensões no ecrã. Sim, quer que as imagens fiquem dentro da IU da aplicação quer esteja num telemóvel ou desktop, mas também deve considerar que aplicações móveis têm viewport muito menores que programas desktop, então deve tentar dar aos dispositivos móveis uma imagem mais pequena para transferir. Em geral (e variando com a região do mundo), telemóveis têm banda mais curta e menos memória que os computadores, então uns KB extra também contam.

Outro desafio é lidar com ecrãs de elevada resolução — gráficos de varredura (bitmaps) pensados para baixas resoluções correm perigo de ficarem minúsculos se apresentados em ecrãs com alta resolução, pelo que os dispositivos aplicam um fator de ampliação às páginas para evitar tal. Infelizmente, imagens de varredura ampliadas podem ficar muito "pixelizadas".

Imagens de fundo em CSS

No caso das imagens de fundo em CSS, isto é fácil de resolver. Segundo a metodologia móvel primeiro, cria-se o layout móvel nas instruções CSS por omissão, ou seja, antes de aplicar quaisquer consultas de média. Depois, as consultas de média disponibilizam CSS que só é aplicado quando o viewport tiver larguar superior a um dado limiar. Vejamos um breve exemplo:

header {
  height: 300px;
  width: 100%;
  background: url(images/small-header.jpg) center;
}

@media all and (min-width: 480px) {
  header {
    background: url(images/large-header.jpg) center;
  }
}

Isto significa que navegadores móveis só vão descarregar a imagem de fundo peqeuna (small-header.jpg), uma vez que não satisfazem a consulta de média, e ignoram a imagem grande (large-header.jpg). Também é possível servir um elemento gráfico com uma resolução mais elevada recorrendo a consultas de média de resolução, como se segue:

button {
  background: url(images/low-res-header.jpg) 1rem center ;
}

@media only screen and (-webkit-min-device-pixel-ratio: 2),
       only screen and ( min-resolution: 192dpi),
       only screen and ( min-resolution: 2dppx) { 
  button {
    background: url(images/high-res-header.jpg) 1rem center ;
  } 
}

Parece complicado mas não é — estamos a utilizar diversas consultas de média, uma vez que, nos dias que correm, diferentes navegadores suportam diferentes consultas de média de resolução (e unidades diferentes — dpi, dppx, sem unidade). Brett Jankord tem uma boa explicação no artigo Cross Browser Retina/High Resolution Media Queries.

<video>

Vídeo em HTML5 está relativamente bem servido em termos de adaptabilidade. Se desejar, pode referir diversos ficheiros com o elemento <source>, cada um com o caminho de um ficheiro e MIME type:

<video controls>
  <source src="videos/720/crystal720.mp4" type="video/mp4">
  <source src="videos/720/crystal720.webm" type="video/webm">
</video>

Mas ainda pode ir um passo mais além. Pode incluir atributos media no elemento <source> com consultas de média — o vídeo carregado no navegador vai depender do formato suportado pelo mesmo e também dos resultados das consultas de média. Por exemplo:

<video controls>
  <source src="videos/320/crystal320.mp4" type="video/mp4" media="all and (max-width: 480px)">
  <source src="videos/320/crystal320.webm" type="video/webm" media="all and (max-width: 480px)">
  <source src="videos/720/crystal720.mp4" type="video/mp4" media="all and (min-width: 481px)">
  <source src="videos/720/crystal720.webm" type="video/webm" media="all and (min-width: 481px)">
</video>

Isto permite ao site servir diferentes ficheiros de vídeo em função no espaço disponível, a fim de otimizar a experiência do utilizador.

<img>

Imagens HTML são uma proposta mais difícil. Não existe mecanismo inerente para servir ficheiros diferentes em função do tamanho do viewport e, devido ao número de comportamentos incómodos dos navegadores, as soluções são mais difíceis de criar do que imagina. Atualmente estão em curso algumas propostas de métodos padrão para realizar esta tarefa  — o "W3C responsive images community group" discutiu este problema durante séculos até chegar ao elemento <picture>, o qual tem estrutura semelhante ao elemento <video>, com alternativas de ficheiro fonte ( <source>  ) selecionáveis através de consultas de média. Outra proposta, srcset, foi avançada pela Apple e usa uma abordagem diferente, que consiste em incluir um atributo srcset em cada elemento <img>, no qual se referem as imagens em conjunto com "dicas" ("hints") que o navegador pode usar para determinar qual é a imagem que mais se adequa ao tamanho do viewport, resolução, etc. Não se pretende que os métodos sejam mutuamente exclusivos.

Isto é tudo muito bonito, mas nenhuma destas soluções está pronta para produção — ambas estão numa fase muito recuada de padronização e não são compatíveis com a maioria dos navegadores. Atualmente temos que depender de em vários Polyfills e outras soluções, nenhuma das quais é perfeita em todas as situações, pelo que cada pessoa deve decidir qual é a solução acertada para a sua situação em particular. Seguem-se algumas soluções disponíveis:

HiSRC
Plugin jQuery que permite criar versões pequenas, médias e grandes de uma imagem, e depois serve a mais apropriada de acordo com a resolução do navegador e velocidade da ligação à internet.
Mobify.js capturing
Uma técnica da Mozilla que permite capturar a fonte da página antes de ser analisada (parsed) pelo navegador. Desta forma, pode-se mudar os atributos src da imagem com JavaScript, de acordo com funcionalidades do navegador, e evitar problemas de pré-carregamento do navegador. É primissor mas ainda não funciona bem em navegadores antigos.
Picturefill
Um polyfill baseado em JavaScript para elementos <picture>, que funciona muito bem, mas necessita de marcação muito especializada.
Adaptive images
Uma solução do lado do servidor, que grava o tamanho do viewport num cookie, e redimensiona imagens através de uma combinação de PHP e .htaccess para um tamanho mais apropriado. Não requer demarcações HTML ou programas JavaScript, mas tem diversas limitações.

SVG e outros gráficos vetoriais

Para certas imagens (não fotografias, mas sim ícones e outros elementos da interface do utilizador), utilizar gráficos vetoriais é uma boa solução. As mesmas são geradas por algoritmos matemáticos em vez de armazenar informação de cada pixel da imagem, pelo que os ficheiros tendem a ser mais pequenos e podem ser facilmente ampliadas ou visualizadas em dispositivos de alta resolução (pelo menos em teoria). Seguem-se algumas ideias, que também ajudam a diminuir o número de pedidos HTTP — outro fator chave no desempenho de aplicações móveis:

  • Tente utilizar CSS3 para gerar efeitos gráficos quando for possível, em vez de recorrer a ficheiros de imagem. Efeitos esses que incluem cantos arredondados, gradientes e sombras. Estes mudam de tamanho à medida que muda a resolução ou o navegador é ampliado, e embora não sejam bem suportados em navegadores antigos como Internet Explorer 6-8, isso não é preocupante se a interface for dirigida a dispositivos modernos como o Firefox OS, e tais navegadores estão graciosamente a cair em desuso.
  • Também pode usar SVG para criar elementos da interface. SVG é um formato de gráficos vetoriais e é bem suportado pelos navegadores modernos, além de que existem polyfills de compatibilidade com navegadores antigos.
  • Utilizar Web fonts para mostrar ícones é uma técnica eficaz para reduzir o tamanho do fichiero e número de pedididos HTTP, e é compatível com navegadores modernos e antigos.

Ver também