Otimizar o carregamento e a renderização de WebFont

Uma WebFont "completa", que inclui todas as variantes de estilo (que podem ser desnecessárias), além de todos os glifos, que podem não ser usados, pode resultar facilmente em um download de vários megabytes. Nesta postagem, você descobrirá como otimizar o carregamento de WebFonts para que os visitantes façam o download apenas do que vão usar.

Para resolver o problema de arquivos grandes contendo todas as variantes, a regra CSS @font-face foi projetada especificamente para permitir que você divida a família de fontes em uma coleção de recursos. Por exemplo, subconjuntos Unicode e variantes de estilo distintas.

Com essas declarações, o navegador identifica os subconjuntos e variantes necessários e faz o download do conjunto mínimo necessário para renderizar o texto, o que é muito conveniente. No entanto, se você não tomar cuidado, isso também pode criar um gargalo de desempenho no caminho crítico de renderização e atrasar a renderização do texto.

O comportamento padrão

O carregamento lento de fontes tem uma implicação oculta importante que pode atrasar a renderização de texto. O navegador precisa construir a árvore de renderização, que depende das árvores do DOM e do CSSOM, antes de saber quais recursos de fonte são necessários para renderizar o texto. Como resultado, as solicitações de fontes são atrasadas bem depois de outros recursos essenciais, e o navegador pode ser impedido de renderizar o texto até que o recurso seja buscado.

Caminho crítico de renderização da fonte

  1. O navegador solicita o documento HTML.
  2. O navegador começa a analisar a resposta HTML e a construir o DOM.
  3. O navegador descobre o CSS, o JS e outros recursos e envia solicitações.
  4. Depois que todo o conteúdo CSS é recebido, o navegador cria o CSSOM e o combina com a árvore do DOM para construir a árvore de renderização.
    • As solicitações de fonte são enviadas depois que a árvore de renderização indica quais variantes de fonte são necessárias para renderizar o texto especificado na página.
  5. O navegador executa o layout e pinta o conteúdo na tela.
    • Se a fonte ainda não estiver disponível, o navegador pode não renderizar nenhum pixel de texto.
    • Depois que a fonte fica disponível, o navegador pinta os pixels de texto.

A "corrida" entre a primeira exibição do conteúdo da página, que pode ser feita logo após a criação da árvore de renderização, e a solicitação do recurso de fonte é o que cria o "problema de texto em branco", em que o navegador pode renderizar o layout da página, mas omite qualquer texto.

Ao pré-carregar WebFonts e usar font-display para controlar como os navegadores se comportam com fontes indisponíveis, você pode evitar páginas em branco e mudanças de layout devido ao carregamento de fontes.

Pré-carregar seus recursos do WebFont

Se for provável que sua página precise de um WebFont específico hospedado em um URL que você conhece com antecedência, aproveite a priorização de recursos. O uso de <link rel="preload"> vai acionar uma solicitação para o WebFont no início do caminho crítico de renderização, sem precisar esperar a criação do CSSOM.

Personalizar o atraso na renderização do texto

Embora o pré-carregamento torne mais provável que uma WebFont esteja disponível quando o conteúdo de uma página for renderizado, ele não oferece garantias. Ainda é preciso considerar como os navegadores se comportam ao renderizar texto que usa uma font-family que ainda não está disponível.

Na postagem Evite texto invisível durante o carregamento da fonte, você pode perceber que o comportamento padrão do navegador não é consistente. No entanto, é possível informar aos navegadores mais recentes como você quer que eles se comportem usando font-display.

Compatibilidade com navegadores

  • 60
  • 79
  • 58
  • 11.1

Origem

De forma semelhante aos comportamentos de tempo limite de fonte que alguns navegadores implementam, o font-display segmenta o ciclo de vida de um download de fonte em três períodos principais:

  1. O primeiro é o período de bloqueio da fonte. Durante esse período, se o tipo de fonte não for carregado, qualquer elemento que tentar usá-lo precisará ser renderizado com um tipo de fonte substituta invisível. Se o tipo de fonte for carregado durante o período de bloqueio, ele será usado normalmente.
  2. O período de troca da fonte ocorre imediatamente após o período de bloqueio da fonte. Durante esse período, se o tipo de fonte não for carregado, qualquer elemento que tentar usá-lo precisará ser renderizado com um tipo de fonte substituta. Se o tipo de fonte for carregado durante o período de troca, ele será usado normalmente.
  3. O período de falha da fonte ocorre imediatamente após o período de troca da fonte. Se o tipo de fonte ainda não tiver sido carregado quando esse período começar, ele vai ser marcado como um carregamento com falha, causando um substituto normal de fonte. Caso contrário, o tipo de fonte será usado normalmente.

Entender esses períodos significa que você pode usar o font-display para decidir como a fonte vai ser renderizada, dependendo do download ou do momento do download.

Para trabalhar com a propriedade font-display, adicione-a às suas regras @font-face:

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  font-display: auto; /* or block, swap, fallback, optional */
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2'), /* will be preloaded */
       url('/fonts/awesome-l.woff') format('woff'),
       url('/fonts/awesome-l.ttf') format('truetype'),
       url('/fonts/awesome-l.eot') format('embedded-opentype');
  unicode-range: U+000-5FF; /* Latin glyphs */
}

No momento, font-display oferece suporte ao seguinte intervalo de valores:

  • auto
  • block
  • swap
  • fallback
  • optional

Para mais informações sobre o pré-carregamento de fontes e a propriedade font-display, consulte as seguintes postagens:

A API FontLoading (em inglês)

Usados juntos, <link rel="preload"> e o CSS font-display oferecem um grande controle sobre o carregamento e a renderização de fontes, sem sobrecarregar. Mas se você precisar de personalizações adicionais e estiver disposto a gerar a sobrecarga introduzida pela execução do JavaScript, há outra opção.

A API Font Load oferece uma interface de script para definir e manipular faces de fontes CSS, acompanhar o progresso do download e substituir o comportamento padrão de carregamento lento. Por exemplo, se tiver certeza de que uma variante de fonte específica é necessária, você pode defini-la e solicitar que o navegador inicie uma busca imediata do recurso de fonte:

Compatibilidade com navegadores

  • 35
  • 79
  • 41
  • 10

Origem

var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", {
  style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});

// don't wait for the render tree, initiate an immediate fetch!
font.load().then(function() {
  // apply the font (which may re-render text and cause a page reflow)
  // after the font has finished downloading
  document.fonts.add(font);
  document.body.style.fontFamily = "Awesome Font, serif";

  // OR... by default the content is hidden,
  // and it's rendered after the font is available
  var content = document.getElementById("content");
  content.style.visibility = "visible";

  // OR... apply your own render strategy here...
});

Além disso, como é possível verificar o status da fonte (usando o método check()) e acompanhar o progresso do download, você também pode definir uma estratégia personalizada para renderizar texto nas suas páginas:

  • É possível reter toda a renderização de texto até que a fonte esteja disponível.
  • Você pode implementar um tempo limite personalizado para cada fonte.
  • É possível usar a fonte substituta para desbloquear a renderização e injetar um novo estilo que usará a fonte desejada depois que ela estiver disponível.

O melhor de tudo é que você também pode misturar e combinar as estratégias acima para diferentes conteúdos da página. Por exemplo, é possível atrasar a renderização de texto em algumas seções até que a fonte esteja disponível, usar uma fonte substituta e renderizar novamente após o download da fonte ser concluído.

O armazenamento em cache adequado é imprescindível

Em geral, os recursos de fonte são estáticos e não têm atualizações frequentes. Consequentemente, elas são ideais para uma expiração longa de max-age. É necessário especificar um cabeçalho ETag condicional e uma política ideal de controle de cache para todos os recursos de fonte.

Se o aplicativo da Web usa um service worker, a disponibilização de recursos de fonte com uma estratégia que prioriza o cache é adequada para a maioria dos casos de uso.

Não armazene fontes usando localStorage ou IndexedDB. Cada um deles tem o próprio conjunto de problemas de desempenho. O cache HTTP do navegador oferece o melhor e mais robusto mecanismo para fornecer recursos de fonte para o navegador.

Lista de verificação de carregamento de fontes da Web

  • Personalize o carregamento e a renderização de fontes usando <link rel="preload">, font-display ou a API Font Loading:o comportamento de carregamento lento padrão pode resultar em atraso na renderização de texto. Esses recursos da plataforma da Web permitem substituir esse comportamento para fontes específicas e especificar estratégias personalizadas de renderização e tempo limite para conteúdos diferentes na página.
  • Especifique as políticas de revalidação e de armazenamento em cache ideais:as fontes são recursos estáticos atualizados com pouca frequência. Verifique se os servidores fornecem um carimbo de data/hora de max-age longo e um token de revalidação para permitir a reutilização eficiente de fontes entre páginas diferentes. Se você estiver usando um service worker, é recomendável usar uma estratégia que prioriza o cache.

Testes automatizados para o comportamento de carregamento do WebFont com o Lighthouse

O Lighthouse pode ajudar a automatizar o processo para garantir que você esteja seguindo as práticas recomendadas de otimização de fontes da Web.

As auditorias a seguir podem ajudar você a garantir que suas páginas continuem seguindo as práticas recomendadas de otimização de fontes da Web ao longo do tempo: