Fonte web que deixa a página em branco: font-display, preload e menos arquivos
Mostre o texto na hora com a fonte do sistema, troque pela fonte da marca quando ela chegar e corte pesos e formatos que ninguém usa.
No 4G da estrada, a página do blog abre com o cabeçalho, as imagens e um vazio onde deveria estar o texto. Dois, três segundos depois, as letras aparecem de uma vez, já na fonte da marca. A pessoa achou que a página estava quebrada e voltou. A resposta curta: use font-display: swap no @font-face, para o navegador mostrar o texto imediatamente com uma fonte do sistema e trocar quando a sua chegar. Depois, reduza o que precisa chegar: sirva WOFF2, só os pesos que você usa, só os caracteres do idioma, e faça preload do arquivo do texto principal.
A fonte da marca continua lá. Ela só deixa de ser condição para a pessoa começar a ler.
Por que o texto fica invisível
Quando o CSS declara uma fonte que ainda não foi baixada, o navegador precisa decidir o que fazer com o texto enquanto espera. O comportamento padrão da maioria dos navegadores é esconder o texto por um tempo, na esperança de que a fonte chegue logo e evite a troca visível. Esse período costuma ser de cerca de três segundos. Se a fonte não chega nesse tempo, o navegador mostra o texto com a fonte reserva e troca depois.
Em rede boa, a fonte chega antes e ninguém percebe. Em rede ruim, a pessoa vê a página sem texto, que é a pior combinação possível: o layout já carregou, mas o conteúdo não. O fenômeno tem nome em inglês, FOIT (flash of invisible text), e o oposto, trocar a fonte com o texto já visível, é FOUT (flash of unstyled text). Para quem quer ler, FOUT é muito melhor.
Há um agravante: o navegador só descobre que precisa da fonte depois de baixar o HTML, baixar o CSS e calcular que algum texto da tela usa aquela família. Se a fonte vem de outro domínio, ainda soma a conexão nova. São várias idas e voltas antes do primeiro byte da fonte.
Os valores de font-display
auto: o navegador decide; na prática, costuma se comportar comoblock.block: esconde o texto por um período curto e troca quando a fonte chega. É o comportamento que causa a página em branco.swap: mostra o texto na hora com a fonte reserva e troca quando a fonte chegar, sem limite de tempo.fallback: esconde por um período muito curto, depois mostra a reserva; se a fonte demorar demais, desiste da troca naquela visita.optional: usa a fonte só se ela estiver disponível quase de imediato, por exemplo em cache; caso contrário, fica com a reserva e não troca.
Para texto corrido, swap é a escolha mais segura. Se a troca visível incomoda muito, optional elimina o pulo e mostra a fonte da marca a partir da segunda página, quando ela já está em cache.
Como deixar a fonte rápida e não bloqueante
- Liste as fontes e pesos usados de verdade, abrindo o CSS computado de títulos, texto, botões e itálicos.
- Hospede os arquivos no seu domínio, se a licença permitir, para evitar a conexão extra.
- Sirva só WOFF2. Todos os navegadores atuais suportam, e ele é o formato mais compacto.
- Recorte os caracteres para o conjunto latino que o português usa.
- Declare
font-display: swapem cada@font-face. - Faça preload só do arquivo do texto principal, não de todos.
- Escolha uma pilha de fontes reserva com métricas parecidas, para a troca mexer pouco no layout.
O @font-face do blog
No exemplo, o blog usava uma família do Google Fonts com seis pesos e itálicos, mais de 400 KB. O texto só usa o regular e o negrito; os títulos usam o negrito. Ficaram dois arquivos.
@font-face {
font-family: "Inter";
src: url("/fontes/inter-400.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Inter";
src: url("/fontes/inter-700.woff2") format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
}
body {
font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
A pilha depois de "Inter" é a fonte reserva: system-ui pega a fonte da interface do sistema, e os nomes seguintes cobrem sistemas mais antigos. Se faltar o itálico, o navegador inclina a fonte regular artificialmente. Para um blog técnico, isso é aceitável e economiza dois arquivos.
O preload no head
<link rel="preload" href="/fontes/inter-400.woff2" as="font" type="font/woff2" crossorigin>
O preload manda o navegador baixar a fonte logo que lê o HTML, sem esperar o CSS. O atributo crossorigin é obrigatório para fontes, mesmo no próprio domínio, porque fontes são buscadas em modo CORS; sem ele, o navegador baixa o arquivo duas vezes. Faça preload de um ou dois arquivos no máximo. Pré-carregar tudo compete com o CSS e as imagens do topo.
Recortando os caracteres
Arquivos de fonte completos trazem cirílico, grego, vietnamita e centenas de símbolos. A ferramenta pyftsubset, do pacote fontTools do Python, gera um arquivo só com o intervalo que você pedir:
pip install fonttools brotli
pyftsubset Inter-Regular.ttf --unicodes="U+0000-00FF,U+2013-2014,U+2018-201D,U+2026,U+20AC" --flavor=woff2 --output-file=inter-400.woff2
O intervalo U+0000-00FF cobre o latim básico e os acentos do português; os outros acrescentam travessões, aspas tipográficas, reticências e o símbolo do euro. O pacote brotli é necessário para gerar WOFF2. No blog do exemplo, cada arquivo caiu para perto de 25 KB. Se você usar o Google Fonts direto, ele já recorta por idioma e aceita o parâmetro display=swap na URL do CSS.
Reduzindo o pulo da troca
Com swap, a troca de fonte pode mudar a largura das linhas e empurrar o texto. Os descritores size-adjust, ascent-override e descent-override no @font-face permitem ajustar a fonte reserva para ocupar quase o mesmo espaço que a sua. O suporte varia entre navegadores, então trate como melhoria: sem ele, a página continua legível. O mesmo cuidado de reservar espaço aparece em imagem com largura e altura.
Como testar com a fonte bloqueada
Nas ferramentas de desenvolvedor do Chrome, aba Network, clique com o botão direito no arquivo da fonte e escolha bloquear a URL da requisição. Recarregue: o texto deve aparecer na fonte do sistema, legível e com o layout inteiro. Depois, remova o bloqueio, limite a rede a uma conexão lenta e observe quanto tempo o texto leva para aparecer. Com swap, deve ser o mesmo tempo do resto do conteúdo. Mais otimizações de carregamento estão em site mais rápido: por onde começar.
Erros comuns
- Deixar o
font-displayno padrão. Em rede lenta, o texto fica invisível por segundos com o resto da página já pronto. - Carregar todos os pesos da família. Cada peso é um arquivo, e a maioria nunca aparece na tela.
- Servir TTF ou vários formatos legados. Os arquivos ficam maiores sem ganho para os navegadores atuais.
- Preload sem
crossorigin. O navegador baixa a fonte duas vezes e o preload vira desperdício. - Preload de todas as fontes. A rede fica congestionada no momento em que o CSS e a imagem principal precisam dela.
- Fonte reserva genérica demais. A troca muda a largura das linhas e o texto pula quando a fonte chega.
Checklist
- Todo
@font-facetemfont-display: swapouoptional. - Só os pesos e estilos usados no CSS são baixados.
- Os arquivos são WOFF2 e recortados para os caracteres do idioma.
- Há preload, com
crossorigin, só da fonte do texto principal. - A pilha de fontes reserva termina numa família genérica como
sans-serif. - Com a fonte bloqueada, a página continua legível e completa.
- O peso total de fontes da página está anotado e é conferido a cada mudança de design.
Bloqueie a URL da fonte principal do seu site nas ferramentas de desenvolvedor e recarregue: o texto aparece na hora, ou a pessoa fica olhando uma página sem palavras?
Referência: https://developer.mozilla.org/docs/Web/CSS/@font-face/font-display