Skip to content

Tudo para WordPress, desenvolvimento web — e não só

⚡ Como carregar web fonts sem perder velocidade e acelerar a renderização do texto

⚡ Como carregar web fonts sem perder velocidade e acelerar a renderização do texto

Quando um site demora 3 segundos a carregar e depois gasta mais um segundo a redesenhar todo o texto, os visitantes vão-se embora. Não para a concorrência, simplesmente fecham o separador. O problema é quase sempre o mesmo: fontes web carregadas sem considerar o desempenho.

De acordo com os dados do HTTP Archive para 2025, cerca de 84% dos sites usam fontes web personalizadas, e o site mediano faz 5 pedidos a ficheiros de fontes, totalizando cerca de 400 KB. Numa ligação fraca, isso significa 2 a 3 segundos de bloqueio de renderização enquanto os utilizadores veem um ecrã em branco. O Google também considera o Cumulative Layout Shift causado pela troca de fontes nas Core Web Vitals.

Os quatro passos abaixo não são teoria. Este é o mínimo prático que resolve a grande maioria dos problemas de desempenho de fontes web. Cada passo demora entre 5 a 15 minutos.

💡 Visão geral rápida:

  • Decida os formatos: woff2 como principal e woff como alternativa é suficiente para todos os navegadores modernos.
  • Adicione preload para as fontes críticas, para que o navegador comece a descarregar imediatamente, em vez de esperar pelo CSS.
  • Verifique o seu font-face: local(), ordem correta de src, unicode-range para caracteres latinos.
  • Defina font-display: swap, e os visitantes veem o texto instantaneamente, mesmo enquanto a fonte ainda está a carregar.

Passo 1: Use woff2 e woff, não é necessário mais nada

Existem muitos formatos de fontes web: EOT, TTF, OTF, SVG. Mas em 2026, só precisa mesmo de dois.

woff2 é o padrão moderno. Os ficheiros são 30% mais pequenos do que woff com a mesma qualidade, porque usam compressão brotli em vez de gzip. O suporte dos navegadores inclui todos os navegadores evergreen, incluindo o Safari móvel e o Samsung Internet. Globalmente, mais de 98% dos utilizadores.

woff é a alternativa para uma pequena fração de navegadores mais antigos (Safari no iOS 11 e versões anteriores, ambientes empresariais raros). Também é comprimido e funciona em todo o lado a partir do IE9+. Mantenha-o em último lugar no src e o navegador usará woff2 se puder; caso contrário, recorrerá ao woff.

Não use EOT (Internet Explorer 8 e versões anteriores) nem TTF (formato bruto, sem compressão) em 2026. A quota desses navegadores é ruído estatístico, e cada formato extra no src aumenta o tamanho do CSS e confunde o navegador.

Se tiver ficheiros em TTF ou OTF, converta-os usando um gerador online. O Transfonter produz woff2 e woff numa só operação, mostrando uma pré-visualização dos glifos e o tamanho final do ficheiro. Uma alternativa é o Font Squirrel Webfont Generator.

Passo 2: Faça preload das fontes críticas

O navegador descobre as fontes através do CSS, e lê o CSS depois do HTML. Quando lá chega, já passaram 500 a 800 ms numa ligação média. O preload elimina este atraso: o navegador começa a descarregar a fonte assim que encontra a tag no <head>, sem esperar pelo CSS.

Tag mínima funcional:

1<link rel="preload" as="font"
2 href="/fonts/open-sans.woff2"
3 type="font/woff2"
4 crossorigin="anonymous">

A chave é crossorigin="anonymous". Sem isto, o navegador ignora a fonte com preload e volta a descarregá-la. A razão é que as fontes são obtidas de forma anónima (CORS), mas o preload sem crossorigin faz um pedido normal. O navegador considera estes recursos diferentes e não os faz corresponder.

O que colocar em preload. Não todas as fontes do site. Apenas a usada para o texto principal acima do dobra (above the fold): cabeçalho, corpo, navegação. O resto pode esperar. Fazer preload de 4 a 5 ficheiros traz retornos decrescentes e rouba largura de banda ao conteúdo crítico.

Nota importante sobre Google Fonts e CDN. Se usar fontes do Google Fonts, os ficheiros são atualizados periodicamente, e um link de preload para uma versão antiga causará um duplo descarregamento (antiga + nova). Em vez de preload para fontes de CDN, use <link rel="preconnect"> para o domínio da fonte. Isto acelera o handshake sem risco de incompatibilidade de versões:

1<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

Prefetch para fontes secundárias. rel="prefetch" diz ao navegador: «este recurso será necessário mais tarde, carrega-o quando o conteúdo principal estiver pronto.» Adequado para fontes em páginas internas ou fontes de ícones no rodapé. A prioridade é baixa, não consome largura de banda.

Um guia moderno sobre priorização de recursos está disponível na documentação do web.dev.

Passo 3: Escreva @font-face corretamente

À primeira vista, @font-face é simples. Na prática, tem quatro áreas subtis, cada uma a afetar a velocidade.

Exemplo de uma declaração correta:

1@font-face {
2 font-family: 'Open Sans';
3 font-weight: 400;
4 font-style: normal;
5 font-display: swap;
6 unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC,
7 U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074,
8 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
9 U+FEFF, U+FFFD;
10 src: local('Open Sans'),
11 url('/fonts/open-sans.woff2') format('woff2'),
12 url('/fonts/open-sans.woff') format('woff');
13}

Análise por pontos:

local(): primeiro no src. Se o utilizador já tiver a fonte instalada no sistema (Roboto no Android, Segoe UI no Windows, San Francisco no macOS), o navegador usa a cópia local e descarrega zero bytes. Coloque sempre local() como a primeira linha no src. Retire o nome do próprio ficheiro da fonte: local('Open Sans') e local('Roboto Regular').

Ordem dos formatos. O navegador percorre o src da esquerda para a direita e usa o primeiro formato que entender. Portanto: local()woff2woff. Nada de EOT/TTF/SVG no final, a menos que tenha um público específico com navegadores antigos, e nesse caso eles vão DEPOIS do woff (não antes).

unicode-range: carregue apenas os glifos de que precisa. Para caracteres latinos, o intervalo U+0000-00FF (Latim Básico + Suplemento Latim-1) é suficiente. São cerca de 250 glifos, contra vários milhares no conjunto completo. O tamanho real do ficheiro diminui 3 a 5 vezes. Não sobrecarregue o intervalo: cada bloco unicode extra adiciona glifos que ninguém verá. Para sites em cirílico, adicione U+0400-04FF.

Ordem dos blocos @font-face. Se tiver vários pesos (regular, negrito, itálico), coloque o peso regular (font-weight: 400) primeiro. O navegador começará a descarregar esse.

Passo 4: Ative font-display: swap e diga adeus ao FOIT

Flash of Invisible Text (FOIT) é quando o navegador esconde o texto durante 3 segundos enquanto espera pela fonte. Os utilizadores veem uma página em branco. Flash of Unstyled Text (FOUT) é quando o texto fica imediatamente visível numa fonte de sistema, sendo depois substituído pela personalizada. O segundo é sempre melhor do que o primeiro.

font-display: swap no @font-face faz exatamente isto: o texto é renderizado instantaneamente numa fonte de sistema e, quando a fonte personalizada carrega, é trocado. Ideal para texto de corpo.

Outros valores e quando usá-los:

  • swap: para texto de corpo. O texto fica visível imediatamente, a substituição é suave.
  • optional: para fontes decorativas e ícones. O navegador decide se descarrega ou não a fonte. Numa ligação fraca, recusará e manterá a fonte de sistema. O período de espera é de 100 ms.
  • block: bloqueio curto (normalmente 3 segundos), depois o texto fica visível, a fonte será trocada quando carregar. Raramente usado.
  • fallback: um compromisso. Bloqueio curto, depois o texto fica visível, a fonte será trocada se carregar rapidamente.

Na prática, use swap para texto de corpo e optional para fontes de ícones e decoração. É suficiente.

Comportamento do navegador sem font-display. Se não especificar nada, o Chrome esconde o texto até 3 segundos, o Firefox até 3 segundos, o Safari indefinidamente e o Edge mostra a fonte de sistema imediatamente. Com font-display: swap, este comportamento torna-se unificado e o resultado é previsível.

Como verificar o resultado

Teste o seu site antes e depois em web.dev/measure. O Lighthouse mostrará «Ensure text remains visible during webfont load» como uma linha separada. Se a auditoria estiver a vermelho, o seu font-display não está a funcionar ou está em falta.

Para verificação manual: abra DevTools → Rede, defina a limitação para «Slow 3G» e atualize a página. O texto deve aparecer instantaneamente numa fonte de sistema, e não após 3 segundos de ecrã em branco.

As capturas de ecrã abaixo mostram a diferença entre a abordagem padrão e a otimizada (teste em Slow 3G):

Carregamento de fontes padrão com bloqueio de texto

Padrão: o texto fica oculto até a fonte carregar

Carregamento otimizado com exibição instantânea de texto

Comportamento otimizado: o texto fica visível imediatamente numa fonte de sistema

A diferença é visível a olho nu: a primeira captura de ecrã mostra um ecrã branco, a segunda mostra o conteúdo disponível instantaneamente.

Na conferência performance.now() 2024, Mandy Michael aborda estratégias avançadas: unicode-range incremental, fatiamento de fontes e trabalho com fontes variáveis. Para quem quiser ir além dos quatro passos básicos.

⁉️🤔 Perguntas frequentes

Porque preciso de woff se o woff2 é suportado em todo o lado?

Os restantes utilizadores de Safari iOS antigo (iOS 11 e versões anteriores) e ambientes empresariais raros com navegadores bloqueados não suportam woff2. Sem uma alternativa woff, estes utilizadores verão uma fonte de sistema em vez da sua. O woff adiciona 15 a 20 KB ao conjunto: um preço insignificante para cobrir a quota restante.

Posso simplesmente usar o Google Fonts e não me preocupar?

Sim, e para a maioria dos sites este é o caminho ideal. O Google Fonts serve automaticamente woff2 para navegadores modernos, usa uma CDN geodistribuída e suporta display=swap como parâmetro de URL. Desvantagens: dependência de uma CDN externa (considerações de privacidade, RGPD), incapacidade de controlar unicode-range e a instalação de fontes locais. Se a privacidade e o controlo forem importantes, aloje as fontes você mesmo.

Como sei se as fontes estão realmente a tornar o meu site mais lento?

O Lighthouse (o separador Auditorias nas Chrome DevTools) mostrará a auditoria «Ensure text remains visible during webfont load». O WebPageTest fornece um gráfico em cascata com o tempo de cada pedido de fonte. Se as fontes começarem depois do primeiro CSS, o preload não está configurado. Se a mudança de layout for superior a 0,1, a fonte está a causar Cumulative Layout Shift, e o Google conta isto nas Core Web Vitals.

font-display: swap estraga o design, o texto «salta» na troca?

Sim, esta é uma desvantagem conhecida do swap. Combata-a com duas técnicas. Primeiro: defina font-size e line-height para o texto de forma a corresponderem à fonte de sistema alternativa. A diferença nas métricas será mínima. Segundo: use o Font Style Matcher ou a propriedade size-adjust no @font-face (disponível em navegadores modernos) para fazer corresponder as métricas da fonte personalizada às da fonte de sistema. Após o ajuste, o CLS será zero.

Devo fazer preload de todas as fontes do site?

Não. Faça preload apenas das fontes críticas: as que compõem o texto acima do dobra (os primeiros 1 a 2 ecrãs). Carregue o resto normalmente através do CSS. Fazer preload de mais de 5 fontes congestiona a largura de banda e atrasa recursos mais importantes na fila. Na prática, 1 a 2 links de preload cobrem a grande maioria dos cenários.

Vale a pena o esforço: quatro passos, quatro minutos

Configurar fontes web não é um projeto de uma semana. Converter para woff2, corrigir o @font-face, o preload e o font-display: swap demora 20 a 30 minutos de trabalho, mesmo que nunca o tenha feito antes.

O benefício é mensurável: o texto fica visível 1,5 a 2,5 segundos mais cedo em Slow 3G. As Core Web Vitals não penalizam pela mudança de layout. E os utilizadores não se vão embora a olhar para um ecrã branco.

Comece com uma fonte: a fonte principal do texto de corpo. Siga os quatro passos. Verifique o Lighthouse antes e depois. A diferença nos números será mais convincente do que qualquer argumento.