Em uma frase
As métricas de font fallback são um conjunto de superpoderes do CSS que esticam e espremem artificialmente uma fonte do sistema para que ela ocupe o mesmíssimo espaço matemático da sua web font customizada, evitando que o layout da página pule violentamente quando a fonte customizada finalmente carregar.
O problema que isso resolve
Para entender o problema, primeiro você precisa entender a guerra tipográfica mais antiga da web: o que a gente mostra pro usuário enquanto espera uma web font customizada de 150KB baixar numa conexão 3G capenga?
Historicamente, os browsers adotavam uma de duas abordagens, e ambas eram terríveis. A primeira era o FOIT (Flash of Invisible Text), onde o browser simplesmente escondia o texto até a fonte baixar. Os usuários ficavam encarando uma tela em branco, se perguntando se o seu site estava quebrado. A segunda era o FOUT (Flash of Unstyled Text), onde o browser renderizava imediatamente o texto usando uma fonte local do sistema (tipo Arial ou Times New Roman), e depois trocava às pressas pela sua web font maravilhosa no milissegundo em que ela chegava.
A comunidade de desenvolvimento web basicamente concordou que o FOUT é melhor para acessibilidade e performance percebida. Afinal, ler um texto feio é melhor do que não ler texto nenhum. Nós formalizamos isso com a regra CSS font-display: swap.
Mas o font-display: swap pariu um novo monstro: o Cumulative Layout Shift (CLS).
Toda fonte tem um esqueleto único. Um "x" na Roboto é fisicamente mais largo que um "x" na Arial. A altura das letras maiúsculas varia. O espaçamento embutido nos arquivos da fonte é completamente diferente. Quando o browser troca a Arial pela Roboto, o texto de repente passa a ocupar uma quantidade diferente de espaço horizontal e vertical. Parágrafos sofrem reflow. O texto quebra para uma nova linha.
Se isso acontece enquanto o usuário já está lendo ou prestes a clicar num botão, a página inteira pula como se um terremoto tivesse acabado de atingir o DOM. Botões fogem debaixo do cursor do usuário. Imagens são empurradas para baixo na página. O Google introduziu as métricas do Core Web Vitals para medir exatamente essa frustração, penalizando pesadamente o SEO de sites com um CLS alto. Nós precisávamos de um jeito de fazer a fonte feia e temporária do sistema imitar perfeitamente as dimensões físicas da fonte customizada bonitona.
Como funciona por debaixo dos panos
Para parar o layout shift, a gente não mexe na web font customizada. Em vez disso, criamos uma versão "Frankenstein" de uma fonte local do sistema usando a regra @font-face. Usamos descritores CSS especializados para sobrescrever (dar um override) a geometria interna da fonte do sistema.
A Anatomia do Box de uma Fonte
Para manipular uma fonte, você precisa entender como o browser calcula o box ao redor de uma linha de texto. Não é só uma questão de font-size. Isso depende de três métricas internas cravadas no próprio arquivo da fonte:
- Ascent: A distância da baseline invisível (onde as letras sentam) até o topo dos caracteres mais altos (tipo o topo de um 'h' ou 'T').
- Descent: A distância da baseline até a base dos caracteres que ficam pendurados mais para baixo (tipo a perninha de um 'y', 'g' ou 'p').
- Line Gap: O espaço vazio recomendado entre o descent de uma linha e o ascent da próxima linha (frequentemente chamado de entrelinha ou leading).
No CSS, a altura total de uma linha de texto é basicamente ascent + descent + line gap. Se a sua fonte customizada e a sua fonte do sistema tiverem valores diferentes para essas três métricas, seu layout vai pular verticalmente. Se as letras tiverem larguras diferentes, seu layout vai pular horizontalmente.
Entram em cena os Overrides
O CSS Fonts Module Level 4 introduziu quatro descritores mágicos que podem ser aplicados dentro de um bloco @font-face. Esses descritores interceptam a leitura que o browser faz das métricas internas do arquivo da fonte e as sobrescrevem na hora (on the fly).
size-adjust: Atua como um multiplicador para a fonte inteira. Se a sua fonte customizada for geralmente mais larga que a Arial, você pode colocar umsize-adjust: 110%na Arial para esticá-la horizontalmente.ascent-override: Sobrescreve a métrica de ascent interna da fonte.descent-override: Sobrescreve a métrica de descent interna da fonte.line-gap-override: Sobrescreve a métrica de line gap interna da fonte.
Juntando a Matemática
O truque é que o size-adjust escala tudo — incluindo as larguras horizontais, o ascent e o descent. Então, se você aumentar a escala de uma fonte do sistema em 110% para fazer a largura das linhas bater com a sua web font, você inadvertidamente deixou a altura vertical da fonte do sistema 110% mais alta, o que causa um layout shift vertical!
Para arrumar isso, os overrides (ascent-override, descent-override, line-gap-override) são calculados como porcentagens do valor do size-adjust, e não do tamanho original da fonte. Você usa o size-adjust para cravar perfeitamente a largura horizontal, e depois usa as métricas de override para dar aquela achatada na altura vertical de volta pra baixo (ou pra cima) para bater exatamente com a bounding box da sua fonte customizada.
Aqui está a cara do código resultante. Repare como criamos uma font family novinha e imaginária chamada Roboto-Fallback que envelopa a fonte local Arial com overrides matematicamente precisos:
/* 1. Load your actual web font */
@font-face {
font-family: 'Roboto';
src: url('/fonts/roboto.woff2') format('woff2');
font-display: swap;
}
/* 2. Create the Frankenstein fallback */
@font-face {
font-family: 'Roboto-Fallback';
src: local('Arial');
/* Stretch Arial horizontally to match Roboto */
size-adjust: 104.5%;
/* Squish Arial's vertical metrics to match Roboto */
ascent-override: 89.92%;
descent-override: 23.44%;
line-gap-override: 0%;
}
/* 3. Use them together in your CSS */
body {
font-family: 'Roboto', 'Roboto-Fallback', sans-serif;
}
Quando a página carrega, o browser pinta instantaneamente a Roboto-Fallback. É só a Arial local, mas esticada na horizontal e achatada na vertical para bater com o footprint matemático exato da Roboto. Quando o arquivo real da Roboto termina de baixar, o swap acontece, as formas das letras mudam de design, mas o layout não move um único pixel.
Histórias do mundo real
A Armadilha do Botão "Cancelar"
Uma gigante do e-commerce estava sofrendo com abandono de carrinho e tickets furiosos no suporte. Os usuários reclamavam que estavam esvaziando seus carrinhos sem querer. A equipe de engenharia gravou as sessões dos usuários e encontrou o culpado. O site carregava uma fonte de marca pesada. O usuário via o botão "Finalizar Compra" bem do lado do botão "Esvaziar Carrinho". Bem na hora que eles clicavam com o mouse em "Finalizar Compra", a fonte da marca carregava. Essa fonte era significativamente mais larga que o padrão do sistema. O texto sofria reflow, empurrando o botão "Finalizar Compra" para a direita, e posicionando o botão "Esvaziar Carrinho" exatamente debaixo do clique certeiro do mouse do usuário. Implementar o size-adjust e os overrides de métrica travou os botões no lugar durante o swap da fonte, derrubando imediatamente a taxa de cancelamentos acidentais.
O Terremoto dos Artigos de Notícias
Um blog de tech super popular passou por um redesign gigantesco, com direito a uma fonte serifada moderna e linda pra leitura longa. Para priorizar a velocidade, eles usaram font-display: swap. Porém, leitores com conexões mais lentas passaram por um fenômeno bizarro: eles carregavam um artigo, desciam uns três parágrafos e começavam a ler. Dois segundos depois, a fonte serifada carregava. Como a fonte serifada tinha um ascent e descent maiores que o padrão do sistema, cada linha de texto crescia uma fração de milímetro. Ao longo de três parágrafos, isso virava uma bola de neve, criando um shift vertical gigantesco e jogando a frase que o usuário estava lendo completamente pra fora da tela. Adicionando um ascent-override e descent-override a uma fallback font local, o texto fez o swap perfeitamente no lugar, mantendo os olhos do leitor exatamente onde deveriam estar.
A Decepção do Score do Lighthouse
Um dev frontend passou três semanas otimizando uma aplicação web para o Core Web Vitals do Google. Comprimiu imagens pra WebP, colocou um defer nos JavaScripts não-críticos e minificou o CSS. Rodou o Google Lighthouse e esperava confiantemente por um score 100 redondinho. Em vez disso, tomou um 75. O relatório acusou uma penalidade pesada de Cumulative Layout Shift. Todo o shift era causado por um único título <H1> quebrando de uma linha pra duas quando uma web font customizada carregava. Em vez de redesenhar o header ou apelar pra textos invisíveis, o dev gerou métricas de fallback exatas para a fonte do título. O layout shift caiu pra zero, o score do Lighthouse bateu 100, e o dev finalmente conseguiu dormir.
Erros e armadilhas comuns
- Chutar as porcentagens: Você não pode fazer esses números no olhômetro. Os cálculos exigem extrair os dados exatos de Unique Units Per Em (UPM), ascent, descent e line gap direto das tabelas binárias dentro dos arquivos tanto da web font quanto da fonte do sistema, e multiplicá-los cruzado. Use sempre um gerador programático para acertar a matemática.
- Aplicar overrides na web font: Uma armadilha clássica é colocar o
size-adjustdireto na declaração@font-faceda web font customizada. Isso não serve pra nada. Os overrides devem ser aplicados numa declaração@font-facecompletamente separada que carrega uma fontelocal()do sistema, que você então coloca em segundo lugar na sua stack defont-family. - Escolher fallbacks estruturalmente opostos: As métricas de fonte têm seus limites. Se a sua fonte customizada for uma sans-serif ultra condensada, e você usar uma fonte serifada larga e cheia de floreios como sua base de fallback local, a matemática do
size-adjustvai fazer a fonte serifada parecer completamente distorcida e ilegível enquanto espera pra fazer o swap. Escolha sempre uma fonte do sistema local que tenha uma estrutura esquelética mais ou menos parecida com a da sua web font. - Esquecer do
line-gap-override: Devs costumam focar totalmente na largura e altura e presumem que deixar o line gap comonormalou simplesmente omitir tá de boa. Se o browser decidir adicionar um leading padrão para a fonte de fallback que não bata perfeitamente com o leading interno da web font, seu ritmo vertical vai sofrer shift. Sempre defina isso explicitamente.
Por que isso deve estar no seu radar
Você devia pensar em métricas de font fallback no exato momento em que decidir usar uma web font customizada em qualquer projeto onde a experiência do usuário e o SEO importam.
Historicamente, tipografia na web era um meio-termo entre estética (usar fontes bonitas) e performance (evitar layouts pulando). Com a chegada das métricas de fonte do CSS, esse meio-termo morreu. Sempre que você estiver auditando os Core Web Vitals de um site, brigando com um score de CLS alto, ou construindo componentes de UI reutilizáveis que não podem se dar ao luxo de tremer na tela, os overrides de font fallback são a solução de engenharia definitiva. Eles transformam as web fonts de um problema de carregamento para uma transição fluida e imperceptível.
Vá mais fundo
- MDN Web Docs: size-adjust - Documentação oficial da Mozilla sobre como o descritor size-adjust escala os outlines e as métricas dos glifos.
- MDN Web Docs: ascent-override - Um mergulho profundo em como dar override na métrica de ascent da fonte.
- web.dev: Improved font fallbacks - Um guia excelente do Google sobre como usar esses exatos descritores CSS para consertar o Cumulative Layout Shift.
- W3C CSS Fonts Module Level 4 - A especificação oficial detalhando a matemática exata e as regras de renderização dos browsers para overrides de métricas de fonte.